From dbc04120791c1ed76c62e8a3eb9a5e5eb927fb86 Mon Sep 17 00:00:00 2001 From: deityhub Date: Tue, 23 Nov 2021 00:10:19 +0100 Subject: [PATCH] update helm for oneuptime --- helm-chart/Dockerfile | 2 +- helm-chart/Dockerfile.dev | 4 +- helm-chart/README.md | 4 +- helm-chart/package.json | 2 +- .../public/cloud-marketplace-install.sh | 10 +- helm-chart/public/index.yaml | 16 +- helm-chart/public/install.sh | 32 +- helm-chart/public/oneuptime/.helmignore | 1 + helm-chart/public/oneuptime/Chart.lock | 12 + helm-chart/public/oneuptime/Chart.yaml | 36 ++ helm-chart/public/oneuptime/LICENSE | 42 +++ helm-chart/public/oneuptime/README.md | 349 ++++++++++++++++++ .../oneuptime/charts/mongodb-10.23.10.tgz | Bin 0 -> 60531 bytes .../charts/nginx-ingress-controller-6.0.1.tgz | Bin 0 -> 23767 bytes .../public/oneuptime/charts/redis-10.5.11.tgz | Bin 0 -> 31223 bytes helm-chart/public/oneuptime/index.yaml | 95 +++++ .../public/oneuptime/templates/NOTES.txt | 85 +++++ .../public/oneuptime/templates/_helpers.tpl | 40 ++ .../public/oneuptime/templates/accounts.yaml | 87 +++++ .../oneuptime/templates/admin-dashboard.yaml | 85 +++++ .../public/oneuptime/templates/api-docs.yaml | 88 +++++ .../templates/application-scanner.yaml | 88 +++++ .../public/oneuptime/templates/backend.yaml | 213 +++++++++++ .../public/oneuptime/templates/configMap.yaml | 11 + .../templates/container-scanner.yaml | 88 +++++ .../public/oneuptime/templates/dashboard.yaml | 93 +++++ .../oneuptime/templates/data-ingestor.yaml | 91 +++++ .../templates/exposed-init-script.yaml | 65 ++++ .../oneuptime/templates/externalMongo.yaml | 33 ++ .../public/oneuptime/templates/haraka.yaml | 86 +++++ .../oneuptime/templates/helm-chart.yaml | 85 +++++ .../public/oneuptime/templates/home.yaml | 88 +++++ .../templates/http-test-server-ingress.yaml | 37 ++ .../templates/http-test-server-tls.yaml | 20 + .../oneuptime/templates/http-test-server.yaml | 83 +++++ .../public/oneuptime/templates/ingress.yaml | 110 ++++++ .../oneuptime/templates/init-script.yaml | 29 ++ .../public/oneuptime/templates/licensing.yaml | 90 +++++ .../oneuptime/templates/lighthouse.yaml | 88 +++++ .../oneuptime/templates/metric-server.yaml | 195 ++++++++++ .../public/oneuptime/templates/probe.yaml | 93 +++++ .../public/oneuptime/templates/realtime.yaml | 83 +++++ .../oneuptime/templates/script-runner.yaml | 87 +++++ .../oneuptime/templates/status-page.yaml | 104 ++++++ .../templates/statusPageIngress.yaml | 44 +++ .../oneuptime/templates/statusPageTls.yaml | 18 + .../oneuptime/templates/tests/test.yaml | 0 .../public/oneuptime/templates/tls.yaml | 17 + helm-chart/public/oneuptime/values.yaml | 328 ++++++++++++++++ 49 files changed, 3322 insertions(+), 35 deletions(-) create mode 100644 helm-chart/public/oneuptime/.helmignore create mode 100644 helm-chart/public/oneuptime/Chart.lock create mode 100644 helm-chart/public/oneuptime/Chart.yaml create mode 100644 helm-chart/public/oneuptime/LICENSE create mode 100644 helm-chart/public/oneuptime/README.md create mode 100644 helm-chart/public/oneuptime/charts/mongodb-10.23.10.tgz create mode 100644 helm-chart/public/oneuptime/charts/nginx-ingress-controller-6.0.1.tgz create mode 100644 helm-chart/public/oneuptime/charts/redis-10.5.11.tgz create mode 100644 helm-chart/public/oneuptime/index.yaml create mode 100644 helm-chart/public/oneuptime/templates/NOTES.txt create mode 100644 helm-chart/public/oneuptime/templates/_helpers.tpl create mode 100644 helm-chart/public/oneuptime/templates/accounts.yaml create mode 100644 helm-chart/public/oneuptime/templates/admin-dashboard.yaml create mode 100644 helm-chart/public/oneuptime/templates/api-docs.yaml create mode 100644 helm-chart/public/oneuptime/templates/application-scanner.yaml create mode 100644 helm-chart/public/oneuptime/templates/backend.yaml create mode 100644 helm-chart/public/oneuptime/templates/configMap.yaml create mode 100644 helm-chart/public/oneuptime/templates/container-scanner.yaml create mode 100644 helm-chart/public/oneuptime/templates/dashboard.yaml create mode 100644 helm-chart/public/oneuptime/templates/data-ingestor.yaml create mode 100644 helm-chart/public/oneuptime/templates/exposed-init-script.yaml create mode 100644 helm-chart/public/oneuptime/templates/externalMongo.yaml create mode 100644 helm-chart/public/oneuptime/templates/haraka.yaml create mode 100644 helm-chart/public/oneuptime/templates/helm-chart.yaml create mode 100644 helm-chart/public/oneuptime/templates/home.yaml create mode 100644 helm-chart/public/oneuptime/templates/http-test-server-ingress.yaml create mode 100644 helm-chart/public/oneuptime/templates/http-test-server-tls.yaml create mode 100644 helm-chart/public/oneuptime/templates/http-test-server.yaml create mode 100644 helm-chart/public/oneuptime/templates/ingress.yaml create mode 100644 helm-chart/public/oneuptime/templates/init-script.yaml create mode 100644 helm-chart/public/oneuptime/templates/licensing.yaml create mode 100644 helm-chart/public/oneuptime/templates/lighthouse.yaml create mode 100644 helm-chart/public/oneuptime/templates/metric-server.yaml create mode 100644 helm-chart/public/oneuptime/templates/probe.yaml create mode 100644 helm-chart/public/oneuptime/templates/realtime.yaml create mode 100644 helm-chart/public/oneuptime/templates/script-runner.yaml create mode 100644 helm-chart/public/oneuptime/templates/status-page.yaml create mode 100644 helm-chart/public/oneuptime/templates/statusPageIngress.yaml create mode 100644 helm-chart/public/oneuptime/templates/statusPageTls.yaml create mode 100644 helm-chart/public/oneuptime/templates/tests/test.yaml create mode 100644 helm-chart/public/oneuptime/templates/tls.yaml create mode 100644 helm-chart/public/oneuptime/values.yaml diff --git a/helm-chart/Dockerfile b/helm-chart/Dockerfile index 738cef9214..e11152bad0 100755 --- a/helm-chart/Dockerfile +++ b/helm-chart/Dockerfile @@ -16,7 +16,7 @@ RUN npm ci --only=production COPY . /usr/src/app # Expose ports. -# - 3423: Fyipe Helm Chart Server +# - 3423: OneUptime Helm Chart Server EXPOSE 3423 #Run the app diff --git a/helm-chart/Dockerfile.dev b/helm-chart/Dockerfile.dev index e6d0722271..39b5b825d6 100644 --- a/helm-chart/Dockerfile.dev +++ b/helm-chart/Dockerfile.dev @@ -1,5 +1,5 @@ # -# Fyipe Docs Dockerfile +# OneUptime Docs Dockerfile # # Pull base image nodejs image. @@ -22,7 +22,7 @@ COPY ./package-lock.json /usr/src/app/package-lock.json RUN npm ci # Expose ports. -# - 3423: Fyipe Helm Chart Server +# - 3423: OneUptime Helm Chart Server EXPOSE 3423 # Expose Debugger port diff --git a/helm-chart/README.md b/helm-chart/README.md index 0792759fad..e9368c10ea 100755 --- a/helm-chart/README.md +++ b/helm-chart/README.md @@ -1,3 +1,3 @@ -# Helm Chart for Fyipe +# Helm Chart for OneUptime -This project contains helm chart for fyipe. +This project contains helm chart for oneuptime. diff --git a/helm-chart/package.json b/helm-chart/package.json index 1968c67944..47d127b7d9 100644 --- a/helm-chart/package.json +++ b/helm-chart/package.json @@ -1,7 +1,7 @@ { "name": "helm-chart", "version": "3.0.0", - "description": "Helm Chart Server for Fyipe", + "description": "Helm Chart Server for OneUptime", "main": "server.js", "scripts": { "preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'", diff --git a/helm-chart/public/cloud-marketplace-install.sh b/helm-chart/public/cloud-marketplace-install.sh index b51925600d..a0acc0a56e 100644 --- a/helm-chart/public/cloud-marketplace-install.sh +++ b/helm-chart/public/cloud-marketplace-install.sh @@ -1,4 +1,4 @@ -# This document is for launching Fyipe VM's on Azure, GCP and AWS. +# This document is for launching OneUptime VM's on Azure, GCP and AWS. # Follow the installation steps below. # Azure: https://docs.microsoft.com/en-us/azure/marketplace/partner-center-portal/azure-vm-create-offer#technical-configuration @@ -7,16 +7,16 @@ # Add these lines to: sudo crontab -e # Run this on Reboot. -@reboot sudo curl https://fyipe.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled +@reboot sudo curl https://oneuptime.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled # Run this once every 24 hours. -0 0 * * * sudo curl https://fyipe.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled +0 0 * * * sudo curl https://oneuptime.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled ## FOR AWS EC2 # Run this on Reboot. -@reboot sudo curl https://fyipe.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled aws-ec2 +@reboot sudo curl https://oneuptime.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled aws-ec2 # Run this once every 24 hours. -0 0 * * * sudo curl https://fyipe.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled aws-ec2 +0 0 * * * sudo curl https://oneuptime.com/chart/install.sh | sudo bash -s thirdPartyBillingEnabled aws-ec2 diff --git a/helm-chart/public/index.yaml b/helm-chart/public/index.yaml index d6d6b9d89d..bad5f266e5 100644 --- a/helm-chart/public/index.yaml +++ b/helm-chart/public/index.yaml @@ -1,6 +1,6 @@ apiVersion: v1 entries: - Fyipe: + OneUptime: - apiVersion: v2 created: "2021-09-10T14:13:26.551683+01:00" dependencies: @@ -15,8 +15,8 @@ entries: version: 14.8.8 description: One complete DevOps and DevOps platform. digest: 84b0d954025bc9d98419d3f7d4ee9e4470db717297e4fc1aaa546af75b16a96a - home: https://fyipe.com - icon: https://fyipe.com/img/Fyipe.svg + home: https://oneuptime.com + icon: https://oneuptime.com/img/Fyipe.svg keywords: - DevOps - IT DevOps @@ -32,11 +32,11 @@ entries: - Website Test - SRE maintainers: - - email: support@fyipe.com - name: Fyipe Support - url: https://fyipe.com/support - name: Fyipe + - email: support@oneuptime.com + name: OneUptime Support + url: https://oneuptime.com/support + name: OneUptime urls: - - Fyipe-3.0.0.tgz + - OneUptime-3.0.0.tgz version: 3.0.0 generated: "2021-09-10T14:13:26.53643+01:00" diff --git a/helm-chart/public/install.sh b/helm-chart/public/install.sh index f8520c3a81..345ead44ad 100755 --- a/helm-chart/public/install.sh +++ b/helm-chart/public/install.sh @@ -1,6 +1,6 @@ # Important: -# This script will setup MicroK8s and install Fyipe on it. -# This is used to install Fyipe on a standalone VM +# This script will setup MicroK8s and install OneUptime on it. +# This is used to install OneUptime on a standalone VM # This is usally used for CI/CD testing, and to update VM's on GCP, Azure and AWS. # If this is the first install, then helm wont be found. @@ -50,7 +50,7 @@ if [[ ! -n $DKIM_PRIVATE_KEY ]]; then openssl rsa -in private -out public -pubout # value of DKIM dns record echo "DKIM DNS TXT Record" - echo "DNS Selector: fyipe._domainkey" + echo "DNS Selector: oneuptime._domainkey" echo "DNS Value: v=DKIM1;p=$(grep -v '^-' public | tr -d '\n')" DKIM_PRIVATE_KEY=$(cat private | base64) fi @@ -143,7 +143,7 @@ then fi -AVAILABLE_VERSION=$(curl https://fyipe.com/api/version | jq '.server' | tr -d '"') +AVAILABLE_VERSION=$(curl https://oneuptime.com/api/version | jq '.server' | tr -d '"') AVAILABLE_VERSION_BUILD=$(echo $AVAILABLE_VERSION | tr "." "0") IMAGE_VERSION=$(sudo k get deployment fi-accounts -o=jsonpath='{$.spec.template.spec.containers[:1].image}' || echo 0) @@ -165,13 +165,13 @@ then fi # Install cluster with Helm. -sudo helm repo add fyipe https://fyipe.com/chart || echo "Fyipe already added" +sudo helm repo add oneuptime https://oneuptime.com/chart || echo "OneUptime already added" sudo helm repo update function updateinstallation { - sudo k delete job fyipe-init-script || echo "init-script already deleted" - sudo helm upgrade --reuse-values fi fyipe/Fyipe \ + sudo k delete job oneuptime-init-script || echo "init-script already deleted" + sudo helm upgrade --reuse-values fi oneuptime/OneUptime \ --set image.tag=$AVAILABLE_VERSION } @@ -188,18 +188,18 @@ then # Chart not deployed. Create a new deployment. Set service of type nodeport for VM's. # Add Admin Email and Password on AWS. - sudo helm install fi fyipe/Fyipe \ + sudo helm install fi oneuptime/OneUptime \ --set isThirdPartyBilling=true \ --set nginx-ingress-controller.service.type=NodePort \ --set nginx-ingress-controller.hostNetwork=true \ --set image.tag=$AVAILABLE_VERSION \ - --set fyipe.admin.email=admin@admin.com \ + --set oneuptime.admin.email=admin@admin.com \ --set disableSignup=true \ - --set fyipe.admin.password=$INSTANCEID + --set oneuptime.admin.password=$INSTANCEID else # Chart not deployed. Create a new deployment. Set service of type nodeport for VM's. This is used for Azure and AWS. - sudo helm install fi fyipe/Fyipe \ + sudo helm install fi oneuptime/OneUptime \ --set isThirdPartyBilling=true \ --set nginx-ingress-controller.service.type=NodePort \ --set nginx-ingress-controller.hostNetwork=true \ @@ -215,27 +215,27 @@ then # install services. if [[ "$2" == "enterprise" ]] then - sudo helm install -f ./kubernetes/values-enterprise-ci.yaml fi ./helm-chart/public/fyipe \ + sudo helm install -f ./kubernetes/values-enterprise-ci.yaml fi ./helm-chart/public/oneuptime \ --set haraka.domain=$DOMAIN \ --set haraka.dkimPrivateKey=$DKIM_PRIVATE_KEY \ --set haraka.tlsCert=$TLS_CERT \ --set haraka.tlsKey=$TLS_KEY else - sudo helm install -f ./kubernetes/values-saas-ci.yaml fi ./helm-chart/public/fyipe \ + sudo helm install -f ./kubernetes/values-saas-ci.yaml fi ./helm-chart/public/oneuptime \ --set haraka.domain=$DOMAIN \ --set haraka.dkimPrivateKey=$DKIM_PRIVATE_KEY \ --set haraka.tlsCert=$TLS_CERT \ --set haraka.tlsKey=$TLS_KEY fi else - sudo k delete job fyipe-init-script || echo "init-script already deleted" - sudo helm upgrade --reuse-values fi ./helm-chart/public/fyipe + sudo k delete job oneuptime-init-script || echo "init-script already deleted" + sudo helm upgrade --reuse-values fi ./helm-chart/public/oneuptime fi else if [[ $DEPLOYED_VERSION_BUILD -eq 0 ]] then # set service of type nodeport for VM's. - sudo helm install fi fyipe/Fyipe \ + sudo helm install fi oneuptime/OneUptime \ --set nginx-ingress-controller.service.type=NodePort \ --set nginx-ingress-controller.hostNetwork=true \ --set image.tag=$AVAILABLE_VERSION \ diff --git a/helm-chart/public/oneuptime/.helmignore b/helm-chart/public/oneuptime/.helmignore new file mode 100644 index 0000000000..191381ee74 --- /dev/null +++ b/helm-chart/public/oneuptime/.helmignore @@ -0,0 +1 @@ +.git \ No newline at end of file diff --git a/helm-chart/public/oneuptime/Chart.lock b/helm-chart/public/oneuptime/Chart.lock new file mode 100644 index 0000000000..fbed12d57b --- /dev/null +++ b/helm-chart/public/oneuptime/Chart.lock @@ -0,0 +1,12 @@ +dependencies: +- name: nginx-ingress-controller + repository: https://charts.bitnami.com/bitnami + version: 6.0.1 +- name: mongodb + repository: https://charts.bitnami.com/bitnami + version: 10.23.10 +- name: redis + repository: https://charts.bitnami.com/bitnami + version: 10.5.11 +digest: sha256:a75a0ffb78f91da3da43a6808df7c9c1d8a5736f512f8e15f6ff67775d3b9ecb +generated: "2021-10-05T18:40:47.90754+01:00" diff --git a/helm-chart/public/oneuptime/Chart.yaml b/helm-chart/public/oneuptime/Chart.yaml new file mode 100644 index 0000000000..0728f01ead --- /dev/null +++ b/helm-chart/public/oneuptime/Chart.yaml @@ -0,0 +1,36 @@ +apiVersion: v2 +name: OneUptime +version: 3.0.0 +description: One complete DevOps and DevOps platform. +keywords: + - DevOps + - IT DevOps + - DevOps + - Monitoring + - Status Page + - On-Call + - On-Call Management + - Incident Management + - Performance Monitoring + - API Test + - Website Monitoring + - Website Test + - SRE +home: https://oneuptime.com +dependencies: +# https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx +- name: nginx-ingress-controller + repository: https://charts.bitnami.com/bitnami + version: "6.0.1" +- name: mongodb + version: "10.23.10" + repository: "https://charts.bitnami.com/bitnami" +- name: redis + version: "10.5.11" + repository: "https://charts.bitnami.com/bitnami" +maintainers: + - name: OneUptime Support + email: support@oneuptime.com + url: https://oneuptime.com/support +icon: https://oneuptime.com/img/Fyipe.svg +engine: gotplhelm dependency update \ No newline at end of file diff --git a/helm-chart/public/oneuptime/LICENSE b/helm-chart/public/oneuptime/LICENSE new file mode 100644 index 0000000000..8a9c104664 --- /dev/null +++ b/helm-chart/public/oneuptime/LICENSE @@ -0,0 +1,42 @@ +End-User License Agreement (EULA) of OneUptime + +This End-User License Agreement ("EULA") is a legal agreement between you and HackerBay, Inc. + +This EULA agreement governs your acquisition and use of our OneUptime software ("Software") directly from HackerBay, Inc. or indirectly through a HackerBay, Inc. authorized reseller or distributor (a "Reseller"). + +Please read this EULA agreement carefully before completing the installation process and using the OneUptime software. It provides a license to use the OneUptime software and contains warranty information and liability disclaimers. + +If you register for a free trial of the OneUptime software, this EULA agreement will also govern that trial. By clicking "accept" or installing and/or using the OneUptime software, you are confirming your acceptance of the Software and agreeing to become bound by the terms of this EULA agreement. + +If you are entering into this EULA agreement on behalf of a company or other legal entity, you represent that you have the authority to bind such entity and its affiliates to these terms and conditions. If you do not have such authority or if you do not agree with the terms and conditions of this EULA agreement, do not install or use the Software, and you must not accept this EULA agreement. + +This EULA agreement shall apply only to the Software supplied by HackerBay, Inc. herewith regardless of whether other software is referred to or described herein. The terms also apply to any HackerBay, Inc. updates, supplements, Internet-based services, and support services for the Software, unless other terms accompany those items on delivery. If so, those terms apply. This EULA was created by EULA Template for OneUptime. + +License Grant +HackerBay, Inc. hereby grants you a personal, non-transferable, non-exclusive licence to use the OneUptime software on your devices in accordance with the terms of this EULA agreement. + +You are permitted to load the OneUptime software under your control. You are responsible for ensuring your device meets the minimum requirements of the OneUptime software. + +You are not permitted to: + +Edit, alter, modify, adapt, translate or otherwise change the whole or any part of the Software nor permit the whole or any part of the Software to be combined with or become incorporated in any other software, nor decompile, disassemble or reverse engineer the Software or attempt to do any such things +Reproduce, copy, distribute, resell or otherwise use the Software for any commercial purpose +Allow any third party to use the Software on behalf of or for the benefit of any third party +Use the Software in any way which breaches any applicable local, national or international law +use the Software for any purpose that HackerBay, Inc. considers is a breach of this EULA agreement +Intellectual Property and Ownership +HackerBay, Inc. shall at all times retain ownership of the Software as originally downloaded by you and all subsequent downloads of the Software by you. The Software (and the copyright, and other intellectual property rights of whatever nature in the Software, including any modifications made thereto) are and shall remain the property of HackerBay, Inc.. + +HackerBay, Inc. reserves the right to grant licences to use the Software to third parties. + +Termination +This EULA agreement is effective from the date you first use the Software and shall continue until terminated. You may terminate it at any time upon written notice to HackerBay, Inc.. + +It will also terminate immediately if you fail to comply with any term of this EULA agreement. Upon such termination, the licenses granted by this EULA agreement will immediately terminate and you agree to stop all access and use of the Software. The provisions that by their nature continue and survive will survive any termination of this EULA agreement. + +Governing Law +This EULA agreement, and any dispute arising out of or in connection with this EULA agreement, shall be governed by and construed in accordance with the laws of us. + +Copyright (C) HackerBay, Inc - All Rights Reserved +Unauthorized copying of this project, via any medium is strictly prohibited +This project is proprietary and confidential \ No newline at end of file diff --git a/helm-chart/public/oneuptime/README.md b/helm-chart/public/oneuptime/README.md new file mode 100644 index 0000000000..e70bec21b8 --- /dev/null +++ b/helm-chart/public/oneuptime/README.md @@ -0,0 +1,349 @@ +# OneUptime + +OneUptime is one complete SRE and DevOps platform. + +OneUptime lets you do: + +**Monitoring:** Monitors your website, web apps, APIs, servers and more and give you detailed metrics of things that might be wrong with your infrastructure. + +**Status Page:** OneUptime gives you a beautiful and customizable status page for your online business which helps improve transparency with your customers and cuts support costs. + +**Tests:** Write automated tests for your website, API's and more and know instantly when they start failing. + +**On-Call and Incident Management:** On-Call Management lets you alert the right team at the right time saving you critical time during downtime. + +**Performance Monitoring:** Monitor the performance of your apps, servers, APIs, and more and alert your team when any of your performance metrics degrades. + +**Website:** https://oneuptime.com + +## TL;DR; + +```console +helm repo add oneuptime https://oneuptime.com/chart +helm repo update +helm install oneuptime oneuptime/OneUptime +``` + +Note: `oneuptime` is your release name. + +## Introduction + +This chart bootstraps a [OneUptime](https://oneuptime.com) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.12+ +- Helm 2.11+ or Helm 3.0-beta3+ +- PV provisioner support in the underlying infrastructure +- ReadWriteMany volumes for deployment scaling + +## Setup SMTP Server (Optional) + +By default, oneuptime will ship with it's own default credential configuration for smtp server. + +### Setup Private Key + +``` +# generate private key +openssl genrsa -out private 2048 + +# Encode it to base64 and export it +export DKIM_PRIVATE_KEY=$(cat private | base64) + +``` + +> If you already have a private key, you can point the export command to it, and export as base64 encoded + +### Setup DKIM on DNS TXT Record + +``` + +# This is the private key created in the above step. +chmod 0400 private + +openssl rsa -in private -out public -pubout + +# value of DKIM DNS record should be... +echo "v=DKIM1;p=$(grep -v '^-' public | tr -d '\n')" + +``` + +> When setting up the DKIM dns txt record (recommended), the selector should be `oneuptime._domainkey` then the value should be the output of the echo command + +### Setup DMARC and SPF DNS TXT Record (Optional) + +To setup dmarc for the smtp server, you need to create a new dns record with the following values + +| Type | Name | Content | +|----------------------|------------------------------------------|---------------------------------------------------------| +| TXT | _dmarc | v=DMARC1; p=reject; adkim=s; aspf=r; rua=mailto:youremail; ruf=mailto:youremail; pct=100 | + +> For SPF dns record, you need to setup with appropriate values, if the ip of the smtp mail server is static, you can add that to the spf ip list + +### Setup tls Keys + +``` +# Unix machine + + +# generate tls_cert.pem and tls_key.pem +# this command will open a prompt for you to fill in your details + +openssl req -x509 -nodes -days 2190 -newkey rsa:2048 -keyout tls_key.pem -out tls_cert.pem + +# Encode your tls to base64 and export it + +export TLS_KEY=$(cat tls_key.pem | base64) +export TLS_CERT=$(cat tls_cert.pem | base64) + +# DOMAIN should equal your domain + +export DOMAIN=$DOMAIN + +``` + +> If you already have tls_key and tls_cert for your domain, you can point the export command to the tls files to generate base64 encoded value + +## Installing the Chart + +To install the chart with the release name `oneuptime`: + +```console +helm repo add oneuptime https://oneuptime.com/chart +helm repo update +helm install oneuptime --set encryptionKey=ThisEncryptionKeyLengthIs32Size. oneuptime/OneUptime +``` + +The command deploys OneUptime on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation. + +Please Note: Encyption Key should be 32 lenth in size. Please change it to any random string you like. you need to keep the encryption key safe, ideally in an encrypted vault. + +## Uninstalling the Chart + +To uninstall/delete the `oneuptime` deployment: + +```console +helm uninstall oneuptime +``` + +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Parameters + +The following table lists the configurable parameters of the OneUptime chart and their default values per section/component: + + +### OneUptime parameters (optional) + +You can add multiple hosts for the oneuptime service. It's in this format: + +``` +oneuptime: + hosts: + host1: + host: + tls: + enabled: false + crt: + key: +``` + +| Parameter | Description | Default | +|---------------------------|-------------------------------------------------|---------------------------------------------------------| +| `oneuptime.host` | Hostname where you want to run oneuptime on | `*` | +| `oneuptime.tls.enabled` | Enable HTTPS | `false` | +| `oneuptime.tls.crt` | Certificale in Base64 format | `nil` | +| `oneuptime.tls.key` | Key in Base64 format | `nil` | + + +### Status Page parameters (optional) + +You can add multiple hosts for the status page. It's in this format: + +``` +statusPage: + hosts: + host1: + host: + tls: + enabled: false + crt: + key: +``` + +**Important:** If you want to run status pages on your subdomain (like status.yourcompany.com). You need to provide OneUptime Host (Yes, `oneuptime.hosts.host1.host` param, NOT `statusPage.hosts.host1.host`). If you specify `statusPage.hosts.host1.host`. Status page will work for that particular host and not for multiple hosts. + +| Parameter | Description | Default | +|---------------------------|-------------------------------------------------|---------------------------------------------------------| +| `statusPage.enabled` | Enable Status Page Ingress | `true` +| `statusPage.host` | Hostname where you want to run your Status Page on, for multiple hosts / status page you leave this blank | `*` | +| `statusPage.tls.enabled` | Enable HTTPS | `false` | +| `statusPage.tls.crt` | Certificale in Base64 format | `nil` | +| `statusPage.tls.key` | Key in Base64 format | `nil` | + + +### Probe parameters [advanced] (optional) + +**What are probes?** +Probes are agents / workers / cron-jobs that monitor your websites at every X interval (default: 1 min. You can change that in dashboard when you create a new website to montor). They not just monitor websites, but also other resources like IoT devices, API's and more. Anything that needs to be monitored by an agent will be monitored by probe. + +You can create any number of probes here. By default, we create two probes, but you can increase or decrease the count. + +| Parameter | Description | Default | +|---------------------------|-------------------------------------------------|---------------------------------------------------------| +| `probes.probe1.port` | Port for probe 1 (specify any unused port) | `*` | +| `probes.probe1.name` | Name of the Probe | `Probe 1` | +| `probes.probe1.key` | Any random key | `sample-key` | +| `probes.probe1.servicePort` | Port to make the probe ping from outside world | `80` | + +You can add any number of probe by specifying `probes.probe.` to your values.yaml. + +### Rate Limitter parameters [advanced] (optional) + +Enable this if you want IP based rate limitting for OneUptime API. + +| Parameter | Description | Default | +|---------------------------|-------------------------------------------------|---------------------------------------------------------| +| `rateLimitter.enabled` | Enable API rate limitter | `false` | +| `rateLimitter.requestLimit` | Limit of requests in a particular time window (see below) | `5000` | +| `rateLimitterrequestLimitTimePeriodInMS` | Rate Limitter window in MS | `216000` | + +## OneUptime Images [advanced] (optional) + +OneUptime Images are loaded from DockerHub by default. Images are public and by default `latest` images are downloaded. We recommend following this tag. OneUptime will handle all the data migration and changes. + +``` +image: + registry: docker.io # Docker Registry where to pull images from. + repository: oneuptimeproject # OneUptime docker repository. + tag: latest # We recommend `latest` tag. + pullPolicy: Always # We recommend Always + restartPolicy: Always # We recommend Always +``` + +## Replicas + +OneUptime by default will start all containers as `1` repicas. To increase replicaCount set + +`replicaCount: ` + +## MongoDB Values + +This is taken from Bitnami Helm Chart. Please refer to https://bitnami.com/stack/mongodb/helm + +Here are default values: + +``` +redis: + redisPort: 6379 + image: + registry: docker.io + repository: bitnami/redis + tag: latest + pullPolicy: Always + usePassword: false + persistence: + enabled: true + mountPath: /bitnami/mongodb + size: 20Gi +``` + + +## Redis Values + +This is taken from Bitnami Helm Chart. Please refer to https://bitnami.com/stack/redis/helm + +Here are default values: + +``` +mongodb: + image: + registry: docker.io + repository: bitnami/mongodb + tag: latest + pullPolicy: Always + mongodbRootPassword: root + mongodbUsername: oneuptime + mongodbPassword: password + mongodbDatabase: oneuptimedb + replicaSet: + enabled: true + name: rs0 + useHostnames: true + key: mongodboneuptime + secondary: 1 + arbiter: 1 + persistence: + enabled: true + mountPath: /bitnami/mongodb + size: 20Gi + useStatefulSet: true +``` + +If you want to expose MongoDB out to the internet, run `install` or `upgrade` with --set mongodb.ingress.enabled=true. You'll see an ingress service for mongodb created with which you can access mongodb data on your cluster. + +## Microk8s + +If you want to install OneUptime on a VM. Add these lines to `sudo crontab -e` + +``` +# Run this on Reboot. +@reboot sudo curl https://oneuptime.com/chart/install.sh | sudo bash + +# Run this once every 24 hours. +0 0 * * * sudo curl https://oneuptime.com/chart/install.sh | sudo bash +``` + +Reboot the machine and wait for 15 mins. + + +## Modifying default params + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```console +helm install oneuptime \ + --set global.imageRegistry=docker.io \ + oneuptime +``` + +## Configuration and installation details + +### [Rolling VS Immutable tags] + +It is strongly recommended to use images tagged with `latest`. OneUptime automatically takes care of data migration if image with tag `latest` updates. + +## Persistence + +Bitnami MongoDB, Redis charts are used as dependencies which takes care of persistence across cloud platforms. + +Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, Azure, and minikube. + +## Update + +To update cluster with new version of OneUptime. Please run: + +``` +VERSION=$(curl https://oneuptime.com/api/version | jq '.server' | tr -d '"') +kubectl delete job oneuptime-init-script || echo "init-script already deleted" +helm upgrade --reuse-values oneuptime oneuptime/OneUptime \ + --set image.tag=$VERSION +``` + +OneUptime automatically takes care of data migration. + +## Things to note + + - If you do not specify TLS config, we will self-sign a certificate for you. +You can also use Cloudflare Universal SSL and run OneUptime service on Port 80 (when you're evaluating. NOT recommended for production) + +## Support + +If you need any help with deployments, please reach out to our engineering support team at support@oneuptime.com and we'll get back to you in less than 1 business day. + +## License + +The project will be deployed on Evaluation License by default. For a commercial license, please reach out to sales@oneuptime.com. + +If you already have a commercial license. Please enter the license key on your dashboard (after you log in to OneUptime) + diff --git a/helm-chart/public/oneuptime/charts/mongodb-10.23.10.tgz b/helm-chart/public/oneuptime/charts/mongodb-10.23.10.tgz new file mode 100644 index 0000000000000000000000000000000000000000..58774ba18abdf9694254d2161620335a3de9abf4 GIT binary patch literal 60531 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 literal 0 HcmV?d00001 diff --git a/helm-chart/public/oneuptime/charts/nginx-ingress-controller-6.0.1.tgz b/helm-chart/public/oneuptime/charts/nginx-ingress-controller-6.0.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c76c265ab79536643969c290a5087002dddbf194 GIT binary patch literal 23767 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

&6 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 DaD|NY literal 0 HcmV?d00001 diff --git a/helm-chart/public/oneuptime/index.yaml b/helm-chart/public/oneuptime/index.yaml new file mode 100644 index 0000000000..ab243589de --- /dev/null +++ b/helm-chart/public/oneuptime/index.yaml @@ -0,0 +1,95 @@ +apiVersion: v1 +entries: + mongodb: + - annotations: + category: Database + apiVersion: v2 + appVersion: 4.4.8 + created: "2021-09-10T14:09:36.396546+01:00" + dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 1.x.x + description: NoSQL document-oriented database that stores JSON-like documents with dynamic schemas, simplifying the integration of data in content-driven applications. + digest: 6c88c641c7aeec1ae15bb03841d704b1e3ff709ca7c792ac9a56c89e8296a64e + home: https://github.com/bitnami/charts/tree/master/bitnami/mongodb + icon: https://bitnami.com/assets/stacks/mongodb/img/mongodb-stack-220x234.png + keywords: + - mongodb + - database + - nosql + - cluster + - replicaset + - replication + maintainers: + - email: containers@bitnami.com + name: Bitnami + name: mongodb + sources: + - https://github.com/bitnami/bitnami-docker-mongodb + - https://mongodb.org + urls: + - charts/mongodb-10.23.10.tgz + version: 10.23.10 + nginx-ingress-controller: + - annotations: + category: Infrastructure + apiVersion: v2 + appVersion: 0.41.2 + created: "2021-09-10T14:09:36.417987+01:00" + description: Chart for the nginx Ingress controller + digest: a40b7483b6b11c8d9c36db0c583d29658b2d484f04175cb31c6202f4d8be37be + home: https://github.com/bitnami/charts/tree/master/bitnami/nginx-ingress-controller + icon: https://bitnami.com/assets/stacks/nginx-ingress-controller/img/nginx-ingress-controller-stack-220x234.png + keywords: + - ingress + - nginx + - http + - web + - www + - reverse proxy + maintainers: + - email: containers@bitnami.com + name: Bitnami + name: nginx-ingress-controller + sources: + - https://github.com/bitnami/bitnami-docker-nginx-ingress-controller + - https://github.com/kubernetes/ingress-nginx + urls: + - charts/nginx-ingress-controller-6.0.1.tgz + version: 6.0.1 + redis: + - annotations: + category: Database + apiVersion: v2 + appVersion: 6.2.5 + created: "2021-09-10T14:09:36.428361+01:00" + dependencies: + - name: common + repository: https://charts.bitnami.com/bitnami + tags: + - bitnami-common + version: 1.x.x + description: Open source, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. + digest: bc737556010607f37747fda35fe4739ed0447bd75f785652d1713a75b643028f + home: https://github.com/bitnami/charts/tree/master/bitnami/redis + icon: https://bitnami.com/assets/stacks/redis/img/redis-stack-220x234.png + keywords: + - redis + - keyvalue + - database + maintainers: + - email: containers@bitnami.com + name: Bitnami + - email: cedric@desaintmartin.fr + name: desaintmartin + name: redis + sources: + - https://github.com/bitnami/bitnami-docker-redis + - http://redis.io/ + urls: + - charts/redis-14.8.8.tgz + version: 10.5.11 +generated: "2021-09-10T14:09:36.3769+01:00" diff --git a/helm-chart/public/oneuptime/templates/NOTES.txt b/helm-chart/public/oneuptime/templates/NOTES.txt new file mode 100644 index 0000000000..94311a0cf2 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/NOTES.txt @@ -0,0 +1,85 @@ +============================================ +IMPORTANT: After Installation Steps +============================================ + +** Thank you for installing OneUptime ** +** Please be patient while the chart is being deployed ** +** This usually takes few minutes or more ** + +To access your OneUptime app from steps below: + +{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }} +============================================ +Make sure external IP's are assigned. +============================================ + +Please run these commands to get OneUptime URL + +$ kubectl get svc {{ .Release.Name }}-nginx-ingress-controller --namespace={{ .Release.Namespace }} + +NOTE: It may take a few minutes for the LoadBalancer IP to be available. +If the load balancer did not assign an external IP yet (if the IP is still pending). +Retry this command after few mins. +{{- end}} +============================================ +Sign Up +============================================ + +{{- if eq (index .Values "nginx-ingress-controller" "service" "type") "LoadBalancer" }} +Go to the External IP (generated from step 1) from your browser and sign up a new admin account. +{{- else}} +Go to the External IP of your server from your browser and sign up a new admin account. +{{- end}} +This is your master admin account (and not a user account). +To create a user account. Please follow steps below. + +============================================ +Setup Email +============================================ + +When you're done signing up the admin account. Head over to "Settings" -> "Email" + +Add your SMTP server details here to enable email alerts. + +============================================ +Setup Twilio +============================================ + +When you're done signing up the admin account. Head over to "Settings" -> "Call and SMS" + +Add your Twilio Settings here to enable call and SMS alert. + +============================================ +Create User +============================================ + +On the Admin Dahboard, go to the "Users" menu and add a new user. +Log out of the admin account, and log in with a user account to access User's OneUptime Dashboard. + +{{- if not $.Values.isThirdPartyBilling }} +============================================ +STEP 5: Buy License +============================================ + +OneUptime which you just installed runs on an evaluation license. +Please contact us at sales@oneuptime.com to buy a commercial license. +We support companies of all sizes. + +Once you buy the commercial license, +you can enter that license key on your admin dashboard. +{{- end }} + +============================================ +Support and Demo +============================================ + +Demo: +If you're looking for a personlized OneUptime demo. +Please email us at demo@oneuptime.com to schedule one. + +Support and Help: +If you're looking for help with anything, +Please email us at support@oneuptime.com and we'll get back to you in less than 1 business day. + + +Thank you for installing OneUptime! diff --git a/helm-chart/public/oneuptime/templates/_helpers.tpl b/helm-chart/public/oneuptime/templates/_helpers.tpl new file mode 100644 index 0000000000..19069f1920 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/_helpers.tpl @@ -0,0 +1,40 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Expand the name of the chart. +*/}} +{{- define "oneuptime.mongodbConnectionString" -}} +{{ printf "mongodb://%s:%s@%s-%s.%s-%s.%s.%s:%s,%s-%s.%s-%s.%s.%s:%s/%s?replicaSet=%s" $.Values.mongodb.auth.username $.Values.mongodb.auth.password $.Release.Name "mongodb-0" $.Release.Name "mongodb-headless" $.Release.Namespace "svc.cluster.local" "27017" $.Release.Name "mongodb-1" $.Release.Name "mongodb-headless" $.Release.Namespace "svc.cluster.local" "27017" $.Values.mongodb.auth.database $.Values.mongodb.replicaSetName }} +{{- end -}} + +{{- define "oneuptime.internalSmtpServer" -}} +{{ printf "%s-haraka.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.redisHost" -}} +{{ printf "%s-redis-master.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.backendHost" -}} +{{ printf "%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.oneuptimeHost" -}} +{{ printf "%s-backend.%s" $.Values.oneuptime.host }} +{{- end -}} + +{{- define "oneuptime.serverUrl" -}} +{{ printf "http://%s-backend.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.scriptRunnerUrl" -}} +{{ printf "http://%s-script.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.dataIngestorUrl" -}} +{{ printf "http://%s-ingestor.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} + +{{- define "oneuptime.realtimeUrl" -}} +{{ printf "http://%s-realtime.%s.%s" $.Release.Name $.Release.Namespace "svc.cluster.local" }} +{{- end -}} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/accounts.yaml b/helm-chart/public/oneuptime/templates/accounts.yaml new file mode 100644 index 0000000000..b3176fe498 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/accounts.yaml @@ -0,0 +1,87 @@ +############-----ACCOUNTS----############################# +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "accounts" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "accounts" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "accounts" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "accounts" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "accounts" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "accounts" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + {{- if .Values.saas.isSaasService }} + - name: STRIPE_PUBLIC_KEY + value: {{ .Values.saas.stripe.publicKey }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: AMPLITUDE_PUBLIC_KEY + value: {{ .Values.saas.amplitude.key }} + {{- end }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.accounts.dsn }} + - name: DISABLE_SIGNUP + value: {{ .Values.disableSignup | quote }} + ports: + - containerPort: {{ .Values.host.accountsPort }} + hostPort: {{ .Values.host.accountsPort }} + name: {{ printf "%s-%s" .Release.Name "accounts" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +# OneUptime Accounts Service +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "accounts" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "accounts" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.accountsServicePort }} + targetPort: {{ .Values.host.accountsPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "accounts" }} + type: ClusterIP +--- +########################################### + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "accounts" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "accounts" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/admin-dashboard.yaml b/helm-chart/public/oneuptime/templates/admin-dashboard.yaml new file mode 100644 index 0000000000..e40907d0cf --- /dev/null +++ b/helm-chart/public/oneuptime/templates/admin-dashboard.yaml @@ -0,0 +1,85 @@ +############-ADMIN-DASHBOARD-######### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "admin" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "admin" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "admin" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "admin" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "admin-dashboard" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "admin" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + {{- if .Values.saas.isSaasService }} + - name: IS_SAAS_SERVICE + value: 'true' + {{- else }} + - name: LICENSE_URL + value: {{ .Values.oneuptime.licensingUrl }} + {{- end }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.adminDashboard.dsn }} + - name: IS_THIRD_PARTY_BILLING + value: {{ .Values.isThirdPartyBilling | quote }} + - name: INTERNAL_SMTP_SERVER + value: {{ template "oneuptime.internalSmtpServer" . }} + ports: + - containerPort: {{ .Values.host.adminDashboardPort }} + hostPort: {{ .Values.host.adminDashboardPort }} + name: {{ printf "%s-%s" .Release.Name "admin" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "admin" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "admin" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.adminDashboardServicePort }} + targetPort: {{ .Values.host.adminDashboardPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "admin" }} + type: ClusterIP +--- +################################## + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "admin" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "admin" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/api-docs.yaml b/helm-chart/public/oneuptime/templates/api-docs.yaml new file mode 100644 index 0000000000..7ffcef664a --- /dev/null +++ b/helm-chart/public/oneuptime/templates/api-docs.yaml @@ -0,0 +1,88 @@ + +#################################### +#IMPORTANT: Kube Reosurces below are ONLY for SaaS service +#################################### + +{{- if .Values.saas.isSaasService }} +###########-----API-DOCS------############## + +# OneUptime API docs Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "api-docs" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "api-docs" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "api-docs" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "api-docs" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "api-docs" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "api-docs" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: IS_SAAS_SERVICE + value: 'true' + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.apiDocs.dsn }} + ports: + - containerPort: {{ .Values.host.apiDocsPort }} + hostPort: {{ .Values.host.apiDocsPort }} + name: {{ printf "%s-%s" .Release.Name "api-docs" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +# OneUptime API docs Service +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "api-docs" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "api-docs" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.apiDocsServicePort }} + protocol: TCP + targetPort: {{ .Values.host.apiDocsPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "api-docs" }} + type: ClusterIP +--- +########################################### +{{- end }} + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "api-docs" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "api-docs" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/application-scanner.yaml b/helm-chart/public/oneuptime/templates/application-scanner.yaml new file mode 100644 index 0000000000..3acad26e2d --- /dev/null +++ b/helm-chart/public/oneuptime/templates/application-scanner.yaml @@ -0,0 +1,88 @@ +#######-------- APPLICATION SCANNER --------######### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "app-scan" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "app-scan" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "app-scan" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "app-scan" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "application-scanner" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "app-scan" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.applicationScanner.dsn }} + - name: PORT + value: {{ .Values.host.applicationScannerPort | quote }} + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" $.Release.Name "configmap" }} + key: clusterkey + ports: + - containerPort: {{ .Values.host.applicationScannerPort }} + hostPort: {{ .Values.host.applicationScannerPort }} + name: {{ printf "%s-%s" .Release.Name "app-scan" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- + +# OneUptime Application Scanner Deployment +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "app-scan" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "app-scan" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.applicationScannerServicePort }} + targetPort: {{ .Values.host.applicationScannerPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "app-scan" }} + type: ClusterIP +--- +################################### + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "app-scan" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "app-scan" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/backend.yaml b/helm-chart/public/oneuptime/templates/backend.yaml new file mode 100644 index 0000000000..cfe4c0c600 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/backend.yaml @@ -0,0 +1,213 @@ +###########-----BACKEND------############## + +# OneUptime Backend Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "backend" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "backend" }} + {{- if $.Values.saas.isRunningOnGCPMarketplace }} + app.kubernetes.io/name: "$name" + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/component: {{ printf "%s-%s" .Release.Name "backend" }} + {{- end }} +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "backend" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "backend" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "backend" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "backend" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 450m + limits: + cpu: 700m + env: + - name: JWT_SECRET + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: encryptionkey + - name: ENCRYPTION_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: encryptionkey + - name: MONGO_URL + value: {{ template "oneuptime.mongodbConnectionString" . }} + {{- if eq .Values.mongodb.architecture "replicaset" }} + - name: IS_MONGO_REPLICA_SET + value: {{ true | quote }} + - name: MONGO_REPLICA_SET_NAME + value: {{ .Values.mongodb.replicaSetName }} + {{- end }} + - name: REDIS_HOST + value: {{ template "oneuptime.redisHost" . }} + - name: ONEUPTIME_HOST + value: {{ .Values.oneuptime.hosts.host1.host }} + - name: BACKEND_PROTOCOL + value: {{ .Values.backendProtocol }} + - name: REDIS_PORT + value: {{ .Values.redis.redisPort | quote }} + - name: PORT + value: {{ .Values.host.backendPort | quote }} + - name: EMAIL_VERIFY_TIME + value: '3600' + - name: BACKEND_HOST + value: {{ .Values.host.backend }} + - name: PUSHNOTIFICATION_PRIVATE_KEY + value: {{ .Values.pushNotification.privateKey }} + - name: PUSHNOTIFICATION_PUBLIC_KEY + value: {{ .Values.pushNotification.publicKey }} + - name: PUSHNOTIFICATION_URL + value: {{ .Values.pushNotification.url }} + - name: SCRIPT_RUNNER_URL + value: {{ template "oneuptime.scriptRunnerUrl" $ }} + - name: REALTIME_URL + value: {{ template "oneuptime.realtimeUrl" $ }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.backend.dsn }} + - name: IS_TESTING + value: {{ .Values.isTesting | quote }} + - name: RATE_LIMITTER_TIME_PERIOD_IN_MS + value: {{ .Values.rateLimitter.requestLimitTimePeriodInMS | quote }} + - name: RATE_LIMITTER_REQUEST_LIMIT + value: {{ .Values.rateLimitter.requestLimit | quote }} + - name: RATE_LIMITTER_ENABLED + value: {{ .Values.rateLimitter.enabled | quote }} + - name: ADMIN_EMAIL + value: {{ .Values.oneuptime.admin.email }} + - name: ADMIN_PASSWORD + value: {{ .Values.oneuptime.admin.password }} + - name: DISABLE_SIGNUP + value: {{ .Values.disableSignup | quote }} + - name: INTERNAL_SMTP_SERVER + value: {{ template "oneuptime.internalSmtpServer" . }} + - name: INTERNAL_SMTP_PORT + value: {{ quote .Values.host.harakaServicePort }} + - name: INTERNAL_SMTP_USER + value: {{ .Values.haraka.user }} + - name: INTERNAL_SMTP_PASSWORD + value: {{ .Values.haraka.password }} + - name: INTERNAL_SMTP_FROM + value: {{ .Values.haraka.fromEmail }} + - name: INTERNAL_SMTP_NAME + value: {{ .Values.haraka.fromName }} + {{- if .Values.newRelic.backend.licenseKey }} + - name: NEW_RELIC_LICENSE_KEY + value: {{ .Values.newRelic.backend.licenseKey }} + {{- end }} + {{- if .Values.newRelic.backend.appName }} + - name: NEW_RELIC_APPLICATION_NAME + value: {{ .Values.newRelic.backend.appName}} + {{- end }} + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: clusterkey + {{- if .Values.saas.isSaasService }} + - name: STRIPE_PUBLIC_KEY + value: {{ .Values.saas.stripe.publicKey }} + - name: STRIPE_PRIVATE_KEY + value: {{ .Values.saas.stripe.privateKey }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: TWITTER_BEARER_TOKEN + value: {{ .Values.saas.twitter.bearertoken }} + - name: AIRTABLE_API_KEY + value: {{ .Values.saas.airtable.key }} + - name: AIRTABLE_BASE_ID + value: {{ .Values.saas.airtable.baseId }} + - name: IS_THIRD_PARTY_BILLING + value: {{ .Values.isThirdPartyBilling | quote }} + - name: SLACK_ERROR_LOG_WEBHOOK + value: {{ .Values.saas.slackErrorLog.webhook }} + - name: SLACK_ERROR_LOG_CHANNEL + value: {{ .Values.saas.slackErrorLog.channel }} + {{- end }} + ports: + - containerPort: {{ .Values.host.backendPort }} + hostPort: {{ .Values.host.backendPort }} + name: {{ printf "%s-%s" .Release.Name "backend" }} + {{- if $.Values.saas.isRunningOnGCPMarketplace }} + - name: ubbagent + image: $imageUbbagent + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: AGENT_CONFIG_FILE + value: "/etc/ubbagent/config.yaml" + - name: AGENT_LOCAL_PORT + value: "4567" + - name: AGENT_ENCODED_KEY + valueFrom: + secretKeyRef: + name: $reportingSecret + key: reporting-key + - name: AGENT_CONSUMER_ID + valueFrom: + secretKeyRef: + name: $reportingSecret + key: consumer-id + volumeMounts: + - name: ubbagent-config + mountPath: /etc/ubbagent + volumes: + - name: ubbagent-config + configMap: + name: ubbagent-config + {{- end }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- +# OneUptime Backend Deployment +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "backend" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "backend" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.backendServicePort }} + targetPort: {{ .Values.host.backendPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "backend" }} + type: ClusterIP +--- +################################################## + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "backend" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "backend" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/configMap.yaml b/helm-chart/public/oneuptime/templates/configMap.yaml new file mode 100644 index 0000000000..11f6f4e91f --- /dev/null +++ b/helm-chart/public/oneuptime/templates/configMap.yaml @@ -0,0 +1,11 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +data: + clusterkey: {{ randAlphaNum 15 | quote }} + encryptionkey: {{ .Values.encryptionKey | quote }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/container-scanner.yaml b/helm-chart/public/oneuptime/templates/container-scanner.yaml new file mode 100644 index 0000000000..93b0c140c3 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/container-scanner.yaml @@ -0,0 +1,88 @@ +#######-------- CONTAINER SCANNER --------######### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "cont-scan" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "cont-scan" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "cont-scan" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "container-scanner" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.containerScanner.dsn }} + - name: PORT + value: {{ .Values.host.containerScannerPort | quote }} + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" $.Release.Name "configmap" }} + key: clusterkey + ports: + - containerPort: {{ .Values.host.containerScannerPort }} + hostPort: {{ .Values.host.containerScannerPort }} + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- + +# OneUptime Container Scanner Deployment +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "cont-scan" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.containerScannerServicePort }} + targetPort: {{ .Values.host.containerScannerPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "cont-scan" }} + type: ClusterIP +--- +################################### + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "cont-scan" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/dashboard.yaml b/helm-chart/public/oneuptime/templates/dashboard.yaml new file mode 100644 index 0000000000..b319aae81d --- /dev/null +++ b/helm-chart/public/oneuptime/templates/dashboard.yaml @@ -0,0 +1,93 @@ +############-----DASHBOARD----############################# +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "dashboard" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "dashboard" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "dashboard" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "dashboard" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "dashboard" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "dashboard" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: DOMAIN + value: {{ .Values.domain }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.dashboard.dsn }} + - name: PUSHNOTIFICATION_PUBLIC_KEY + value: {{ .Values.pushNotification.publicKey }} + {{- if .Values.statusPageDomain }} + - name: STATUSPAGE_DOMAIN + value: {{ .Values.statusPageDomain }} + {{- end }} + {{- if .Values.saas.isSaasService }} + - name: STRIPE_PUBLIC_KEY + value: {{ .Values.saas.stripe.publicKey }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: AMPLITUDE_PUBLIC_KEY + value: {{ .Values.saas.amplitude.key }} + {{- end }} + ports: + - containerPort: {{ .Values.host.dashboardPort }} + hostPort: {{ .Values.host.dashboardPort }} + name: {{ printf "%s-%s" .Release.Name "dashboard" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +# OneUptime Dashoard Service +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "dashboard" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "dashboard" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.dashboardServicePort }} + targetPort: {{ .Values.host.dashboardPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "dashboard" }} + type: ClusterIP +--- +########################################################## + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "dashboard" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "dashboard" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/data-ingestor.yaml b/helm-chart/public/oneuptime/templates/data-ingestor.yaml new file mode 100644 index 0000000000..6cb19d3f95 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/data-ingestor.yaml @@ -0,0 +1,91 @@ +########-ingestor-################# +#ingestor service and deployement +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "ingestor" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "ingestor" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "ingestor" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "ingestor" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "data-ingestor" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "ingestor" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 450m + limits: + cpu: 700m + env: + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: PORT + value: {{ .Values.host.dataIngestorPort | quote }} + - name: MONGO_URL + value: {{ template "oneuptime.mongodbConnectionString" . }} + - name: SCRIPT_RUNNER_URL + value: {{ template "oneuptime.scriptRunnerUrl" $ }} + - name: REALTIME_URL + value: {{ template "oneuptime.realtimeUrl" $ }} + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: clusterkey + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.dataIngestor.dsn }} + ports: + - containerPort: {{ .Values.host.dataIngestorPort }} + hostPort: {{ .Values.host.dataIngestorPort }} + name: {{ printf "%s-%s" .Release.Name "ingestor" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "ingestor" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "ingestor" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.dataIngestorServicePort }} + targetPort: {{ .Values.host.dataIngestorPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "ingestor" }} + type: ClusterIP +--- +########################### + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "ingestor" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "ingestor" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/exposed-init-script.yaml b/helm-chart/public/oneuptime/templates/exposed-init-script.yaml new file mode 100644 index 0000000000..aecc64273b --- /dev/null +++ b/helm-chart/public/oneuptime/templates/exposed-init-script.yaml @@ -0,0 +1,65 @@ + +#################################### +#IMPORTANT: Kube Reosurces below are ONLY for SaaS service +#################################### + +{{- if .Values.saas.exposeInitScriptContainer }} +###########-----init-script------################# +# OneUptime init-script +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "init-script" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "init-script" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "init-script" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "init-script" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "init-script" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "init-script" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: IS_SAAS_SERVICE + value: 'true' + - name: NODE_ENV + value: 'development' + - name: ONEUPTIME_HOST + value: {{ .Values.oneuptime.hosts.host1.host }} + ports: + - containerPort: {{ .Values.host.initScriptPort }} + hostPort: {{ .Values.host.initScriptPort }} + name: {{ printf "%s-%s" .Release.Name "init-script" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "init-script" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "init-script" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.initScriptServicePort }} + protocol: TCP + targetPort: {{ .Values.host.initScriptPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "init-script" }} + type: ClusterIP +--- +########################################### +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/externalMongo.yaml b/helm-chart/public/oneuptime/templates/externalMongo.yaml new file mode 100644 index 0000000000..eb3baa74df --- /dev/null +++ b/helm-chart/public/oneuptime/templates/externalMongo.yaml @@ -0,0 +1,33 @@ +# We don't need this again to expose our mongodb to the outside world +# All the configuration should be done in the values.yaml file +{{- if .Values.mongodb.ingress.enabled }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ printf "%s-%s" $.Release.Name "mongo-external" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +data: + 27017: {{ printf "%s/$s" $.Release.Namespace "fi-mongodb:27017" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ printf "%s-%s" $.Release.Name "mongo-ingress" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + type: LoadBalancer + ports: + - name: proxied-tcp-27017 + port: 27017 + targetPort: 27017 + protocol: TCP + selector: + app: mongodb +{{- end }} +--- \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/haraka.yaml b/helm-chart/public/oneuptime/templates/haraka.yaml new file mode 100644 index 0000000000..3f9f2a308c --- /dev/null +++ b/helm-chart/public/oneuptime/templates/haraka.yaml @@ -0,0 +1,86 @@ +{{- if .Values.haraka.domain -}} +############-----HARAKA----############################# +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "haraka" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "haraka" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "haraka" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "haraka" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "haraka" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "haraka" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: SMTP_USER + value: {{ .Values.haraka.user }} + - name: SMTP_PASSWORD + value: {{ .Values.haraka.password }} + - name: DOMAIN + value: {{ .Values.haraka.domain }} + - name: DKIM_PRIVATE_KEY + value: {{ .Values.haraka.dkimPrivateKey }} + - name: TLS_CERT + value: {{ .Values.haraka.tlsCert }} + - name: TLS_KEY + value: {{ .Values.haraka.tlsKey }} + ports: + - containerPort: {{ .Values.host.harakaPort }} + hostPort: {{ .Values.host.harakaPort }} + name: {{ printf "%s-%s" .Release.Name "haraka" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +# OneUptime Haraka Service +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "haraka" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "haraka" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.harakaServicePort }} + targetPort: {{ .Values.host.harakaPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "haraka" }} + type: ClusterIP +--- +########################################################## +{{- end -}} + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "haraka" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "haraka" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/helm-chart.yaml b/helm-chart/public/oneuptime/templates/helm-chart.yaml new file mode 100644 index 0000000000..b17384781a --- /dev/null +++ b/helm-chart/public/oneuptime/templates/helm-chart.yaml @@ -0,0 +1,85 @@ + +#################################### +#IMPORTANT: Kube Reosurces below are ONLY for SaaS service +#################################### + +{{- if .Values.saas.isSaasService }} +###########-----HELM CHART------################# +# OneUptime HELM CHART +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "helm-chart" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "helm-chart" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "helm-chart" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "helm-chart" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "helm-chart" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "helm-chart" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: IS_SAAS_SERVICE + value: 'true' + - name: NODE_ENV + value: 'production' + ports: + - containerPort: {{ .Values.host.helmChartPort }} + hostPort: {{ .Values.host.helmChartPort }} + name: {{ printf "%s-%s" .Release.Name "helmchart" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "helm-chart" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "helm-chart" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.helmChartServicePort }} + protocol: TCP + targetPort: {{ .Values.host.helmChartPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "helm-chart" }} + type: ClusterIP +--- +########################################### +{{- end }} + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "helm-chart" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "helm-chart" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/home.yaml b/helm-chart/public/oneuptime/templates/home.yaml new file mode 100644 index 0000000000..ac8573322d --- /dev/null +++ b/helm-chart/public/oneuptime/templates/home.yaml @@ -0,0 +1,88 @@ + +#################################### +#IMPORTANT: Kube Reosurces below are ONLY for SaaS service +#################################### + +{{- if .Values.saas.isSaasService }} +###########-----HOME------################# +# OneUptime Home +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "home" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "home" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "home" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "home" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "home" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "home" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: IS_SAAS_SERVICE + value: 'true' + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.home.dsn }} + - name: ONEUPTIME_HOST + value: {{ .Values.oneuptime.hosts.host1.host }} + ports: + - containerPort: {{ .Values.host.homePort }} + hostPort: {{ .Values.host.homePort }} + name: {{ printf "%s-%s" .Release.Name "home" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "home" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "home" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.homeServicePort }} + protocol: TCP + targetPort: {{ .Values.host.homePort }} + selector: + app: {{ printf "%s-%s" .Release.Name "home" }} + type: ClusterIP +--- +########################################### +{{- end }} + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "home" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "home" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/http-test-server-ingress.yaml b/helm-chart/public/oneuptime/templates/http-test-server-ingress.yaml new file mode 100644 index 0000000000..9074ccbf31 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/http-test-server-ingress.yaml @@ -0,0 +1,37 @@ +############----TEST-SERVER-INGRESS--##################################### +{{- if .Values.saas.isSaasService }} +{{- range $key, $value := $.Values.httpTestServer.hosts }} +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: nginx + ingress.kubernetes.io/ssl-redirect: "true" + name: {{ printf "%s-%s-%s" $.Release.Name $key "test" }} + namespace: {{ $.Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + {{- if $value.tls.enabled }} + tls: + - hosts: + - {{ $value.host }} + secretName: {{ printf "%s-%s-%s" $.Release.Name $key "testtls" }} + {{- end }} + rules: + {{- if $value.host }} + - host: {{ $value.host }} + http: + {{- else }} + - http: + {{- end }} + paths: + - path: / + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "test" }} + servicePort: 80 +--- +{{- end }} +{{- end }} +################################## \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/http-test-server-tls.yaml b/helm-chart/public/oneuptime/templates/http-test-server-tls.yaml new file mode 100644 index 0000000000..7fdf6beeeb --- /dev/null +++ b/helm-chart/public/oneuptime/templates/http-test-server-tls.yaml @@ -0,0 +1,20 @@ +{{- if .Values.saas.isSaasService }} +{{- range $key, $value := $.Values.httpTestServer.hosts }} +{{- if $value.tls.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-%s-%s" $.Release.Name $key "testtls" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +type: Opaque +data: + tls.crt: {{ $value.tls.crt }} + tls.key: {{ $value.tls.key }} +--- +{{- end }} +{{- end }} +{{- end }} + diff --git a/helm-chart/public/oneuptime/templates/http-test-server.yaml b/helm-chart/public/oneuptime/templates/http-test-server.yaml new file mode 100644 index 0000000000..fb54311741 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/http-test-server.yaml @@ -0,0 +1,83 @@ +###########-----TEST-SERVER------################# +{{- if .Values.saas.isSaasService }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "test" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "test" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "test" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "test" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "http-test-server" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "test" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: ONEUPTIME_HOST + value: {{ .Values.oneuptime.hosts.host1.host }} + {{- if .Values.saas.isSaasService }} + - name: IS_SAAS_SERVICE + value: 'true' + {{- end }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.httpTestServer.dsn }} + ports: + - containerPort: {{ .Values.host.httpTestServerPort }} + hostPort: {{ .Values.host.httpTestServerPort }} + name: {{ printf "%s-%s" .Release.Name "test" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "test" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "test" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.httpTestServerServicePort }} + targetPort: {{ .Values.host.httpTestServerPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "test" }} + type: ClusterIP +--- +{{- end }} +######################################## + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "test" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "test" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/ingress.yaml b/helm-chart/public/oneuptime/templates/ingress.yaml new file mode 100644 index 0000000000..fd021693b0 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/ingress.yaml @@ -0,0 +1,110 @@ +############----INGRESS---##################################### +{{- range $key, $value := $.Values.oneuptime.hosts }} +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + meta.helm.sh/release-name: {{ printf "%s" $.Release.Name }} + annotations: + kubernetes.io/ingress.class: nginx + ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/affinity-mode: "balanced" + nginx.ingress.kubernetes.io/session-cookie-change-on-failure: "false" + nginx.ingress.kubernetes.io/session-cookie-name: "fi-ingress-cookie" + nginx.ingress.kubernetes.io/session-cookie-expires: "172800" + ingress.kubernetes.io/session-cookie-hash: "sha1" + nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" + name: {{ printf "%s-%s-%s" $.Release.Name $key "ingress" }} + namespace: {{ $.Release.Namespace }} +spec: + {{- if $value.tls.enabled }} + tls: + - hosts: + - {{ $value.host }} + secretName: {{ printf "%s-%s-%s" $.Release.Name $key "tls" }} + {{- end }} + rules: + {{- if $value.host }} + - host: {{ $value.host }} + http: + {{- else }} + - http: + {{- end }} + paths: + - path: /accounts + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }} + servicePort: 80 + - path: /data-ingestor + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "ingestor" }} + servicePort: 80 + - path: /dashboard + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "dashboard" }} + servicePort: 80 + - path: /admin + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "admin" }} + servicePort: 80 + - path: /api + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "backend" }} + servicePort: 80 + - path: /realtime + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "realtime" }} + servicePort: 80 + - path: /status-page + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "status" }} + servicePort: 80 + - path: /haraka + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "haraka" }} + servicePort: 80 + - path: /script + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "script" }} + servicePort: 80 + {{- range $probeKey, $probeValue := $.Values.probes }} + - path: {{ printf "/%s" $probeKey }} + backend: + serviceName: {{ printf "%s-%s" $.Release.Name $probeKey }} + servicePort: 80 + {{- end }} + {{- if $.Values.saas.isSaasService }} + - path: / + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "home" }} + servicePort: 80 + - path: /docs + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "api-docs" }} + servicePort: 80 + - path: /license + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "licensing" }} + servicePort: 80 + - path: /chart + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "helm-chart" }} + servicePort: 80 + {{- else }} + - path: / + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "accounts" }} + servicePort: 80 + {{- end }} + {{- if $.Values.saas.exposeInitScriptContainer }} + - path: / + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "init-script" }} + servicePort: 80 + {{- end }} +--- +{{- end }} +########################################################################## diff --git a/helm-chart/public/oneuptime/templates/init-script.yaml b/helm-chart/public/oneuptime/templates/init-script.yaml new file mode 100644 index 0000000000..33c431679f --- /dev/null +++ b/helm-chart/public/oneuptime/templates/init-script.yaml @@ -0,0 +1,29 @@ +########-INIT-SCRIPT-########## +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ printf "%s-%s" .Release.Name "init-script" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + template: + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "init-script" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "init-script" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: MONGO_URL + value: {{ template "oneuptime.mongodbConnectionString" . }} + - name: NODE_ENV + value: 'production' + - name: ENCRYPTION_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: encryptionkey + restartPolicy: Never +--- +#################################### \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/licensing.yaml b/helm-chart/public/oneuptime/templates/licensing.yaml new file mode 100644 index 0000000000..664ee16b49 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/licensing.yaml @@ -0,0 +1,90 @@ + +#################################### +#IMPORTANT: Kube Reosurces below are ONLY for SaaS service +#################################### + +{{- if .Values.saas.isSaasService }} +###########-----LICENSING------############## +# Licensing +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "licensing" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "licensing" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "licensing" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "licensing" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "licensing" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "licensing" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: IS_SAAS_SERVICE + value: 'true' + - name: AIRTABLE_API_KEY + value: {{ .Values.saas.licensing.airtable.key }} + - name: AIRTABLE_BASE_ID + value: {{ .Values.saas.licensing.airtable.baseId }} + - name: TOKEN_SECRET + value: {{ .Values.saas.licensing.tokenSecret }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.licensing.dsn }} + ports: + - containerPort: {{ .Values.host.licensingPort }} + hostPort: {{ .Values.host.licensingPort }} + name: {{ printf "%s-%s" .Release.Name "licensing" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "licensing" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "licensing" }} +spec: + ports: + - port: {{ .Values.host.licensingServicePort }} + protocol: TCP + targetPort: {{ .Values.host.licensingPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "licensing" }} + type: ClusterIP +--- +{{- end }} + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "licensing" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "licensing" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/lighthouse.yaml b/helm-chart/public/oneuptime/templates/lighthouse.yaml new file mode 100644 index 0000000000..6756914e26 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/lighthouse.yaml @@ -0,0 +1,88 @@ +#######-------- LIGHTHOUSE RUNNER --------######### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "lighthouse" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "lighthouse" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "lighthouse" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "lighthouse-runner" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.lighthouse.dsn }} + - name: PORT + value: {{ .Values.host.lighthouseRunnerPort | quote }} + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" $.Release.Name "configmap" }} + key: clusterkey + ports: + - containerPort: {{ .Values.host.lighthouseRunnerPort }} + hostPort: {{ .Values.host.lighthouseRunnerPort }} + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- + +# OneUptime Lighthouse Runner Deployment +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "lighthouse" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.lighthouseRunnerServicePort }} + targetPort: {{ .Values.host.lighthouseRunnerPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "lighthouse" }} + type: ClusterIP +--- +################################### + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "lighthouse" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/metric-server.yaml b/helm-chart/public/oneuptime/templates/metric-server.yaml new file mode 100644 index 0000000000..c8783d78ce --- /dev/null +++ b/helm-chart/public/oneuptime/templates/metric-server.yaml @@ -0,0 +1,195 @@ +# Default configuration for a metric server +# https://github.com/kubernetes-sigs/metrics-server + +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + k8s-app: metrics-server + rbac.authorization.k8s.io/aggregate-to-admin: "true" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + rbac.authorization.k8s.io/aggregate-to-view: "true" + name: system:aggregated-metrics-reader +rules: +- apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + k8s-app: metrics-server + name: system:metrics-server +rules: +- apiGroups: + - "" + resources: + - pods + - nodes + - nodes/stats + - namespaces + - configmaps + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + k8s-app: metrics-server + name: metrics-server-auth-reader + namespace: kube-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + k8s-app: metrics-server + name: metrics-server:system:auth-delegator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + k8s-app: metrics-server + name: system:metrics-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:metrics-server +subjects: +- kind: ServiceAccount + name: metrics-server + namespace: kube-system +--- +apiVersion: v1 +kind: Service +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +spec: + ports: + - name: https + port: 443 + protocol: TCP + targetPort: https + selector: + k8s-app: metrics-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + k8s-app: metrics-server + name: metrics-server + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: metrics-server + strategy: + rollingUpdate: + maxUnavailable: 0 + template: + metadata: + labels: + k8s-app: metrics-server + spec: + containers: + - args: + - --cert-dir=/tmp + - --secure-port=443 + - --kubelet-preferred-address-types=Hostname,InternalDNS,InternalIP,ExternalDNS,ExternalIP + - --kubelet-use-node-status-port + - --metric-resolution=15s + image: k8s.gcr.io/metrics-server/metrics-server:v0.5.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: https + scheme: HTTPS + periodSeconds: 10 + name: metrics-server + ports: + - containerPort: 443 + name: https + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /readyz + port: https + scheme: HTTPS + initialDelaySeconds: 20 + periodSeconds: 10 + resources: + requests: + cpu: 100m + memory: 200Mi + securityContext: + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1000 + volumeMounts: + - mountPath: /tmp + name: tmp-dir + nodeSelector: + kubernetes.io/os: linux + priorityClassName: system-cluster-critical + serviceAccountName: metrics-server + volumes: + - emptyDir: {} + name: tmp-dir +--- +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + labels: + k8s-app: metrics-server + name: v1beta1.metrics.k8s.io +spec: + group: metrics.k8s.io + groupPriorityMinimum: 100 + insecureSkipTLSVerify: true + service: + name: metrics-server + namespace: kube-system + version: v1beta1 + versionPriority: 100 diff --git a/helm-chart/public/oneuptime/templates/probe.yaml b/helm-chart/public/oneuptime/templates/probe.yaml new file mode 100644 index 0000000000..9a9b2eb31c --- /dev/null +++ b/helm-chart/public/oneuptime/templates/probe.yaml @@ -0,0 +1,93 @@ +########-PROBE-################# +#Probe service and deployement +{{- range $key, $value := $.Values.probes }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" $.Release.Name $key }} + namespace: {{ $.Release.Namespace }} + labels: + app: {{ printf "%s-%s" $.Release.Name $key }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" $.Release.Name $key }} + replicas: 1 # THIS SHOULD STRICTLY BE 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" $.Release.Name $key }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" $.Values.image.registry $.Values.image.repository "probe" $.Values.image.tag }} + name: {{ printf "%s-%s" $.Release.Name $key }} + imagePullPolicy: {{ $.Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: DATA_INGESTOR_URL + value: {{ template "oneuptime.dataIngestorUrl" $ }} + - name: PORT + value: {{ $value.port | quote }} + - name: PROBE_NAME + value: {{ $value.name }} + - name: PROBE_KEY + value: {{ $value.key }} + {{- if $.Values.newRelic.probe.licenseKey }} + - name: NEW_RELIC_LICENSE_KEY + value: {{ $.Values.newRelic.probe.licenseKey }} + {{- end }} + {{- if $.Values.newRelic.probe.appName }} + - name: NEW_RELIC_APPLICATION_NAME + value: {{ $.Values.newRelic.probe.appName}} + {{- end }} + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" $.Release.Name "configmap" }} + key: clusterkey + {{- if $.Values.saas.isSaasService }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: SLACK_ERROR_LOG_WEBHOOK + value: {{ $.Values.saas.slackErrorLog.webhook }} + - name: SLACK_ERROR_LOG_CHANNEL + value: {{ $.Values.saas.slackErrorLog.channel }} + {{- end }} + - name: NODE_ENV + value: {{ $.Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ $.Values.sentry.probe.dsn }} + ports: + - containerPort: {{ $value.port }} + hostPort: {{ $value.port }} + name: {{ printf "%s-%s" $.Release.Name $key }} + restartPolicy: {{ $.Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" $.Release.Name $key }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" $.Release.Name $key }} + namespace: {{ $.Release.Namespace }} +spec: + ports: + - port: {{ $value.servicePort }} + targetPort: {{ $value.port }} + selector: + app: {{ printf "%s-%s" $.Release.Name $key }} + type: ClusterIP +--- +########################### +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/realtime.yaml b/helm-chart/public/oneuptime/templates/realtime.yaml new file mode 100644 index 0000000000..f943e19757 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/realtime.yaml @@ -0,0 +1,83 @@ +########-REALTIME-################# +#realtime service and deployement +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "realtime" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "realtime" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "realtime" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "realtime" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "realtime" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "realtime" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 450m + limits: + cpu: 700m + env: + - name: PORT + value: {{ .Values.host.realtimePort | quote }} + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" .Release.Name "configmap" }} + key: clusterkey + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.realtime.dsn }} + ports: + - containerPort: {{ .Values.host.realtimePort }} + hostPort: {{ .Values.host.realtimePort }} + name: {{ printf "%s-%s" .Release.Name "realtime" }} + restartPolicy: {{ .Values.image.restartPolicy }} + +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "realtime" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "realtime" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.realtimeServicePort }} + targetPort: {{ .Values.host.realtimePort }} + selector: + app: {{ printf "%s-%s" .Release.Name "realtime" }} + type: ClusterIP +--- +########################### + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "realtime" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "realtime" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/script-runner.yaml b/helm-chart/public/oneuptime/templates/script-runner.yaml new file mode 100644 index 0000000000..5630b74efb --- /dev/null +++ b/helm-chart/public/oneuptime/templates/script-runner.yaml @@ -0,0 +1,87 @@ +#######------SCRIPT RUNNER--------########## + +# OneUptime Script Runner Deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "script" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "script" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "script" }} + replicas: 1 + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "script" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "script-runner" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "script" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.scriptRunner.dsn }} + - name: SERVER_URL + value: {{ template "oneuptime.serverUrl" $ }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: CLUSTER_KEY + valueFrom: + configMapKeyRef: + name: {{ printf "%s-%s" $.Release.Name "configmap" }} + key: clusterkey + ports: + - containerPort: {{ .Values.host.scriptRunnerPort }} + hostPort: {{ .Values.host.scriptRunnerPort }} + name: {{ printf "%s-%s" .Release.Name "script" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- +# OneUptime Script Runner Deployment +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "script" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "script" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.scripRunnerServicePort }} + targetPort: {{ .Values.host.scriptRunnerPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "script" }} + type: ClusterIP +--- +################################### + + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "script" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "script" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/status-page.yaml b/helm-chart/public/oneuptime/templates/status-page.yaml new file mode 100644 index 0000000000..60a0641809 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/status-page.yaml @@ -0,0 +1,104 @@ +###########-----STATUS PAGE------################# +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ printf "%s-%s" .Release.Name "status" }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ printf "%s-%s" .Release.Name "status" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + selector: + matchLabels: + app: {{ printf "%s-%s" .Release.Name "status" }} + replicas: {{ .Values.replicaCount }} + template: + metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "status" }} + spec: + containers: + - image: {{ printf "%s/%s/%s:%s" .Values.image.registry .Values.image.repository "status-page" .Values.image.tag }} + name: {{ printf "%s-%s" .Release.Name "status" }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + resources: + requests: + cpu: 250m + limits: + cpu: 500m + env: + - name: ONEUPTIME_HOST + value: {{ .Values.oneuptime.hosts.host1.host }} + - name: NODE_ENV + value: {{ .Values.nodeEnv }} + - name: SENTRY_DSN + value: {{ .Values.sentry.statusPage.dsn }} + - name: BACKEND_URL + value: {{ template "oneuptime.backendHost" . }} + - name: MONGO_URL + value: {{ template "oneuptime.mongodbConnectionString" . }} + {{- if .Values.saas.isSaasService }} + - name: IS_SAAS_SERVICE + value: 'true' + - name: STATUSPAGE_CERT + value: {{ .Values.statusPage.cert }} + - name: STATUSPAGE_PRIVATEKEY + value: {{ .Values.statusPage.key }} + {{- end }} + {{- if .Values.backendProtocol }} + - name: BACKEND_PROTOCOL + value: {{ .Values.backendProtocol }} + {{- end }} + ports: + - containerPort: {{ .Values.host.statusPageHttpPort }} + hostPort: {{ .Values.host.statusPageHttpPort }} + name: {{ printf "%s-%s" .Release.Name "status-http" }} + - containerPort: {{ .Values.host.statusPageHttpsPort }} + hostPort: {{ .Values.host.statusPageHttpsPort }} + name: {{ printf "%s-%s" .Release.Name "status-https" }} + restartPolicy: {{ .Values.image.restartPolicy }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: {{ printf "%s-%s" .Release.Name "status" }} + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm + name: {{ printf "%s-%s" .Release.Name "status" }} + namespace: {{ .Release.Namespace }} +spec: + ports: + - port: {{ .Values.host.statusPageHttpServicePort }} + name: "http" + targetPort: {{ .Values.host.statusPageHttpPort }} + - port: {{ .Values.host.statusPageHttpsServicePort }} + name: "https" + targetPort: {{ .Values.host.statusPageHttpsPort }} + selector: + app: {{ printf "%s-%s" .Release.Name "status" }} + {{- if .Values.saas.isSaasService }} + # Load balancer becasue we need to expose Status page on different domains. + type: LoadBalancer + {{- else}} + type: ClusterIP + {{- end }} +--- +######################################## + +{{- if .Values.autoScaler.enabled }} +apiVersion: autoscaling/v1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ printf "%s-%s" .Release.Name "status" }} +spec: + maxReplicas: {{ .Values.autoScaler.maxReplicas }} + minReplicas: {{ .Values.autoScaler.minReplicas }} + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ printf "%s-%s" .Release.Name "status" }} + targetCPUUtilizationPercentage: {{ .Values.autoScaler.averageCpuUtilization }} +--- +{{- end }} \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/statusPageIngress.yaml b/helm-chart/public/oneuptime/templates/statusPageIngress.yaml new file mode 100644 index 0000000000..97a806c92b --- /dev/null +++ b/helm-chart/public/oneuptime/templates/statusPageIngress.yaml @@ -0,0 +1,44 @@ +############----STATUS-PAGE-INGRESS--##################################### +{{- if .Values.oneuptime.hosts.host1.host }} +{{- range $key, $value := $.Values.statusPage.hosts }} +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + annotations: + kubernetes.io/ingress.class: nginx + ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/affinity: "cookie" + nginx.ingress.kubernetes.io/affinity-mode: "balanced" + nginx.ingress.kubernetes.io/session-cookie-change-on-failure: "false" + nginx.ingress.kubernetes.io/session-cookie-name: "fi-ingress-cookie" + nginx.ingress.kubernetes.io/session-cookie-expires: "172800" + ingress.kubernetes.io/session-cookie-hash: "sha1" + nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" + name: {{ printf "%s-%s-%s" $.Release.Name $key "statuspage" }} + namespace: {{ $.Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +spec: + {{- if $value.tls.enabled }} + tls: + - hosts: + - {{ $value.host }} + secretName: {{ printf "%s-%s-%s" $.Release.Name $key "statuspagetls" }} + {{- end }} + rules: + {{- if $value.host }} + - host: {{ $value.host }} + http: + {{- else }} + - http: + {{- end }} + paths: + - path: / + backend: + serviceName: {{ printf "%s-%s" $.Release.Name "status" }} + servicePort: 80 +--- +{{- end }} +{{- end }} +################################## \ No newline at end of file diff --git a/helm-chart/public/oneuptime/templates/statusPageTls.yaml b/helm-chart/public/oneuptime/templates/statusPageTls.yaml new file mode 100644 index 0000000000..02bdd7f735 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/statusPageTls.yaml @@ -0,0 +1,18 @@ +{{- range $key, $value := $.Values.statusPage.hosts }} +{{- if $value.tls.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-%s-%s" $.Release.Name $key "statuspagetls" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +type: Opaque +data: + tls.crt: {{ $value.tls.crt }} + tls.key: {{ $value.tls.key }} +--- +{{- end }} +{{- end }} + diff --git a/helm-chart/public/oneuptime/templates/tests/test.yaml b/helm-chart/public/oneuptime/templates/tests/test.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/helm-chart/public/oneuptime/templates/tls.yaml b/helm-chart/public/oneuptime/templates/tls.yaml new file mode 100644 index 0000000000..7084af7c96 --- /dev/null +++ b/helm-chart/public/oneuptime/templates/tls.yaml @@ -0,0 +1,17 @@ +{{- range $key, $value := $.Values.oneuptime.hosts }} +{{- if $value.tls.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ printf "%s-%s-%s" $.Release.Name $key "tls" }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/part-of: oneuptime + app.kubernetes.io/managed-by: Helm +type: Opaque +data: + tls.crt: {{ $value.tls.crt }} + tls.key: {{ $value.tls.key }} +--- +{{- end }} +{{- end }} diff --git a/helm-chart/public/oneuptime/values.yaml b/helm-chart/public/oneuptime/values.yaml new file mode 100644 index 0000000000..95c0482798 --- /dev/null +++ b/helm-chart/public/oneuptime/values.yaml @@ -0,0 +1,328 @@ +################################################################################## +## Important: If you're implenting this in the enterprise environment, this should always be `false`. +## This is for OneUptime SaaS service. This will deploy all the SaaS env vars +################################################################################## +saas: + exposeInitScriptContainer: false + isSaasService: false + stripe: + publicKey: #Stripe public and private key + privateKey: + airtable: + key: #Airtbale key to store leads. + baseId: + amplitude: + key: #Amplitude for tracking. + twitter: + bearertoken: # Twitter Bearer Token. + licensing: + airtable: # Airtable for validating licenses. + key: + baseId: + tokenSecret: # Encrypting lisense with tokens to send them to clients. + +################################################################################### + +statusPage: + hosts: + host1: + host: + tls: + enabled: false + crt: + key: + cert: # certificate for a custom domain + key: # private key for a custom domain + +################################################################################## +## Important: OneUptime Values. More information in the Readme.md +################################################################################## +oneuptime: + admin: + email: + password: + hosts: + host1: + host: + tls: + enabled: false + crt: + key: + licensingUrl: https://oneuptime.com/license + +################################################################################### + +httpTestServer: + hosts: + host1: + host: + tls: + enabled: false + crt: + key: + +################################################################################## +## Important: Probe Values. More information in the Readme.md +################################################################################## + +probes: + probe1: + port: 3024 + name: Probe 1 + key: sample-key + servicePort: 80 + probe2: + name: Probe 2 + port: 3025 + key: sample-key + servicePort: 80 + +################################################################################## +## Important: RateLimitter Values. More information in the Readme.md +################################################################################## + +rateLimitter: + enabled: false + requestLimit: 5000 + requestLimitTimePeriodInMS: 216000 + + +## OneUptime official image version on Docker Hub +## ref: https://hub.docker.com/u/oneuptimeproject +## + +image: + registry: docker.io + repository: oneuptimeproject + tag: latest + pullPolicy: Always + restartPolicy: Always + +replicaCount: 1 + +################################################################################## +## IMPORTANT: +## Values for Subcharts +## + +redis: + redisPort: 6379 + image: + registry: docker.io + repository: bitnami/redis + tag: latest + pullPolicy: Always + usePassword: false + auth: + enabled: false + persistence: + enabled: true + mountPath: /bitnami/redis + size: 20Gi + + +mongodb: + architecture: replicaset + auth: + enabled: true + rootPassword: root + username: oneuptime + password: password + database: oneuptimedb + replicaSetKey: mongodboneuptime + replicaSetName: rs0 + replicaCount: 2 + replicaSetHostnames: true + arbiter: + enabled: true + image: + registry: docker.io + repository: bitnami/mongodb + tag: latest + pullPolicy: Always + # Uncomment this field to enable external access + # to mongodb database + # If the mongodb is failing to initialise, comment out the variable below {externalAccess, serviceAccount, rbac} + # After reinstall the project again + # Once deployed successfully, uncomment the variables and upgrade the project + externalAccess: + enabled: true + service: + type: LoadBalancer + port: 27017 + autoDiscovery: + enabled: true + serviceAccount: + create: true + rbac: + create: true + # end of file for external access selectors + persistence: + enabled: true + mountPath: /bitnami/mongodb + size: 1000Gi + useStatefulSet: true + ingress: + enabled: false + +## Service Configuration +## For minikube, set service.type to NodePort, elsewhere use LoadBalancer +## + +## Service Configuration +## For minikube, set this to NodePort, elsewhere use LoadBalancer +## +nginx-ingress-controller: + defaultBackend: + enabled: false + service: + type: LoadBalancer + proxySetHeaders: + X-Forwarded-For: $http_x_forwarded_for + X-Real-Ip: $http_x_forwarded_for + publishService: + enabled: true + config: + log-format-upstream: '$remote_addr - $http_cf_connecting_ip - $http_x_forwarded_for - $request_id - [$proxy_add_x_forwarded_for] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status' + proxy-protocol: "true" + real-ip-header: "X-Forwarded-For" + + + ################################################################################## + +haraka: + fromEmail: + fromName: + user: + password: + domain: + # This should be base64 of your private key + dkimPrivateKey: + tlsCert: + tlsKey: + +host: + backendPort: 3002 + dataIngestorPort: 3200 + realtimePort: 3300 + homePort: 1444 + licensingPort: 3004 + statusPageHttpPort: 3006 + statusPageHttpsPort: 3007 + dashboardPort: 3000 + accountsPort: 3003 + helmChartPort: 3423 + apiDocsPort: 1445 + initScriptPort: 1447 + # if port 25 is avaialble and accessible + # then we can use it as default port + harakaPort: 2525 + httpTestServerPort: 3010 + adminDashboardPort: 3100 + backendServicePort: 80 + dataIngestorServicePort: 80 + realtimeServicePort: 80 + homeServicePort: 80 + apiDocsServicePort: 80 + statusPageHttpServicePort: 80 + statusPageHttpsServicePort: 443 + dashboardServicePort: 80 + accountsServicePort: 80 + adminDashboardServicePort: 80 + backendNodePort: 80 + statusPageNodePort: 80 + dashboardNodePort: 80 + accountsNodePort: 80 + adminDashboardNodePort: 80 + licensingServicePort: 80 + helmChartServicePort: 80 + httpTestServerServicePort: 80 + initScriptServicePort: 80 + harakaServicePort: 2525 + scriptRunnerPort: 3009 + scripRunnerServicePort: 80 + applicationScannerPort: 3005 + applicationScannerServicePort: 80 + containerScannerPort: 3055 + containerScannerServicePort: 80 + lighthouseRunnerPort: 3015 + lighthouseRunnerServicePort: 80 + +isThirdPartyBilling: false +isRunningOnGCPMarketplace: false +isTesting: false + +# Encryption Key +encryptionKey: ThisEncryptionKeyLengthIs32Size. + +# If you disable sign up, then you need to specify +# oneuptime.admin.email and oneuptime.admin.password values for the admin account. +disableSignup: false + +# What protocol is backend running on. Takes in values like 'http:' or 'https:' +backendProtocol: + +# Status page domain to add to CNAME to work with custom domains +# Status page CNAME to display whcih customers will set on the cusom domain tab of status page. +statusPageDomain: + +# Push notificaitons. +# Generate public and pivate key for push notifications. +# These are just the test keys. +# You can generate them by: +# First install the web-push npm package using npm install web-push -g, then run web-push generate-vapid-keys + +pushNotification: + publicKey: "BD1kb-OchZlXr32bmwpjhoxp_cq-aqK4dWXRDkC5m6Hd9_cvMOUw_bXRFR3pJFGzpEdjQUk5SDdYaXvb7xd-1Dg" + privateKey: "WdFZTeXkuoxpsO_KNOtXvhDUc_Ae1rb-WjPv6AVexA4" + url: "https://oneuptime-test.com" + + +autoScaler: + enabled: false + averageCpuUtilization: 50 + minReplicas: 1 + maxReplicas: 1 + +newRelic: + backend: + licenseKey: + appName: + probe: + licenseKey: + appName: + +nodeEnv: development +sentry: + backend: + dsn: + dashboard: + dsn: + accounts: + dsn: + adminDashboard: + dsn: + apiDocs: + dsn: + applicationScanner: + dsn: + containerScanner: + dsn: + dataIngestor: + dsn: + home: + dsn: + httpTestServer: + dsn: + licensing: + dsn: + lighthouse: + dsn: + probe: + dsn: + realtime: + dsn: + scriptRunner: + dsn: + statusPage: + dsn: \ No newline at end of file