From ea295b6d9e243c329ab87d04823a2e261b636478 Mon Sep 17 00:00:00 2001 From: Dejan Zele Pejchev Date: Thu, 13 Jun 2024 13:56:50 +0200 Subject: [PATCH] remove outdated docs and broken references; remove broken quickstart Signed-off-by: Dejan Zele Pejchev --- .devcontainer/demo/README.md | 24 - .devcontainer/demo/devcontainer.json | 18 - .devcontainer/demo/jobs.yaml | 24 - .devcontainer/demo/start.sh | 15 - README.md | 20 + deployment/armada-bundle/.helmignore | 23 - deployment/armada-bundle/Chart.lock | 33 - deployment/armada-bundle/Chart.yaml | 46 - deployment/armada-bundle/README.md | 131 -- .../templates/pulsar-init-job.yaml | 43 - deployment/armada-bundle/values.yaml | 267 ---- .../armada-bundle/values/example.values.yaml | 273 ---- docs/demo.md | 181 --- docs/developer/aws-ec2.md | 236 ---- docs/developer/etcd-localdev.md | 74 -- docs/developer/manual-localdev.md | 75 -- docs/developer/ubuntu-setup.md | 173 --- docs/local/armadactl.sh | 40 - docs/local/destroy.sh | 17 - docs/local/setup.sh | 165 --- docs/quickstart/grafana-armada-dashboard.json | 1156 ----------------- .../values-executor-cluster-monitoring.yaml | 5 - .../helm/values-executor-prometheus.yaml | 22 - docs/quickstart/helm/values-executor.yaml | 11 - docs/quickstart/helm/values-pulsar.yaml | 54 - docs/quickstart/helm/values-redis.yaml | 3 - .../helm/values-server-prometheus.yaml | 20 - docs/quickstart/helm/values-server.yaml | 40 - docs/quickstart/img/grafana-screenshot.png | Bin 117093 -> 0 bytes docs/quickstart/index.md | 129 -- docs/quickstart/job-queue-a-preemptive.yaml | 23 - docs/quickstart/job-queue-b.yaml | 23 - .../quickstart/kind/kind-config-executor.yaml | 7 - docs/quickstart/kind/kind-config-server.yaml | 12 - docs/quickstart/priority-class-example.yaml | 8 - docs/quickstart/queue-a.yaml | 15 - docs/quickstart/queue-b.yaml | 25 - .../example-job.yaml | 0 example/kind-config.yaml | 5 - magefiles/ci.go | 2 +- plugins/armadactl.yml | 6 +- scripts/get-armadactl.sh | 61 + 42 files changed, 85 insertions(+), 3420 deletions(-) delete mode 100644 .devcontainer/demo/README.md delete mode 100644 .devcontainer/demo/devcontainer.json delete mode 100644 .devcontainer/demo/jobs.yaml delete mode 100755 .devcontainer/demo/start.sh delete mode 100644 deployment/armada-bundle/.helmignore delete mode 100644 deployment/armada-bundle/Chart.lock delete mode 100644 deployment/armada-bundle/Chart.yaml delete mode 100644 deployment/armada-bundle/README.md delete mode 100644 deployment/armada-bundle/templates/pulsar-init-job.yaml delete mode 100644 deployment/armada-bundle/values.yaml delete mode 100644 deployment/armada-bundle/values/example.values.yaml delete mode 100644 docs/demo.md delete mode 100644 docs/developer/aws-ec2.md delete mode 100644 docs/developer/etcd-localdev.md delete mode 100644 docs/developer/manual-localdev.md delete mode 100644 docs/developer/ubuntu-setup.md delete mode 100755 docs/local/armadactl.sh delete mode 100755 docs/local/destroy.sh delete mode 100755 docs/local/setup.sh delete mode 100644 docs/quickstart/grafana-armada-dashboard.json delete mode 100644 docs/quickstart/helm/values-executor-cluster-monitoring.yaml delete mode 100644 docs/quickstart/helm/values-executor-prometheus.yaml delete mode 100644 docs/quickstart/helm/values-executor.yaml delete mode 100644 docs/quickstart/helm/values-pulsar.yaml delete mode 100644 docs/quickstart/helm/values-redis.yaml delete mode 100644 docs/quickstart/helm/values-server-prometheus.yaml delete mode 100644 docs/quickstart/helm/values-server.yaml delete mode 100644 docs/quickstart/img/grafana-screenshot.png delete mode 100644 docs/quickstart/index.md delete mode 100644 docs/quickstart/job-queue-a-preemptive.yaml delete mode 100644 docs/quickstart/job-queue-b.yaml delete mode 100644 docs/quickstart/kind/kind-config-executor.yaml delete mode 100644 docs/quickstart/kind/kind-config-server.yaml delete mode 100644 docs/quickstart/priority-class-example.yaml delete mode 100644 docs/quickstart/queue-a.yaml delete mode 100644 docs/quickstart/queue-b.yaml rename docs/quickstart/job-queue-a.yaml => example/example-job.yaml (100%) delete mode 100644 example/kind-config.yaml create mode 100755 scripts/get-armadactl.sh diff --git a/.devcontainer/demo/README.md b/.devcontainer/demo/README.md deleted file mode 100644 index 1221fbeffee..00000000000 --- a/.devcontainer/demo/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Run - -Run this when the script completes - -```bash -# If you are at the root of the repo -cd .devcontainer/demo -./armadactl create queue test --priority-factor 1 -./armadactl submit jobs.yaml -./armadactl watch test job-set-1 -``` - -# View Lookout - -If you want to view lookout, click the bottom right icon and select "Open in Vscode Desktop". - -Forward these ports: - -- 8089: Lookout -- 8082: Binoculars -- 10000: Lookoutv2 API -- 8080: Armada Server API - -and go to: http://localhost:8089 diff --git a/.devcontainer/demo/devcontainer.json b/.devcontainer/demo/devcontainer.json deleted file mode 100644 index 027ea964a92..00000000000 --- a/.devcontainer/demo/devcontainer.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "image": "mcr.microsoft.com/devcontainers/universal:2", - "features": { - "ghcr.io/mpriscella/features/kind:1": {} - }, - "postAttachCommand": "./start.sh", - "customizations": { - "vscode": { - "extensions": [ - "golang.go", - "ms-python.python" - ] - } - }, - // Open workspace in .devcontainer/demo folder - "workspaceFolder": "/workspaces/armada/.devcontainer/demo", - "name": "Demo" - } \ No newline at end of file diff --git a/.devcontainer/demo/jobs.yaml b/.devcontainer/demo/jobs.yaml deleted file mode 100644 index 47473cfe3c8..00000000000 --- a/.devcontainer/demo/jobs.yaml +++ /dev/null @@ -1,24 +0,0 @@ -queue: test -jobSetId: job-set-1 -jobs: - - priority: 0 - namespace: personal-anonymous - podSpec: - terminationGracePeriodSeconds: 0 - restartPolicy: Never - containers: - - name: sleep - imagePullPolicy: IfNotPresent - image: alpine:latest - command: - - sh - - -c - args: - - sleep $(( (RANDOM % 30) + 30 )) - resources: - limits: - memory: 64Mi - cpu: 150m - requests: - memory: 64Mi - cpu: 150m \ No newline at end of file diff --git a/.devcontainer/demo/start.sh b/.devcontainer/demo/start.sh deleted file mode 100755 index 0dbff52073f..00000000000 --- a/.devcontainer/demo/start.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -sh ../../docs/local/armadactl.sh - -cd ../../ - -export ARMADA_IMAGE=gresearchdev/armada-full-bundle-dev -export ARMADA_IMAGE_TAG=a08830b4911c6784d67d1227367f8505243fd167 - -# Install mage -go install github.com/magefile/mage@latest - -# Run the demo -mage localdev no-build - diff --git a/README.md b/README.md index 4f0ff26c5a9..4b560ece826 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,26 @@ For an overview of Armada, see the following videos: The Armada project adheres to the CNCF [Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +## Installation + +### Armada Operator + +For installation instructions, easiest way is to use the Armada Operator. +For more information, see the [Armada Operator repository](https://github.com/armadaproject/armada-operator). + +Alternatively, you can install Armada manually by using the Helm charts defined in the `deployment` directory. + +### armadactl + +Armada also provides a command-line interface, `armadactl`, which can be used to interact with the Armada system. + +To install `armadactl`, run the following script: +```bash +scripts/get-armadactl.sh +``` + +Or download it from the [GitHub Release](https://github.com/armadaproject/armada/releases/latest) page for your platform. + ## Documentation For documentation, see the following: diff --git a/deployment/armada-bundle/.helmignore b/deployment/armada-bundle/.helmignore deleted file mode 100644 index 0e8a0eb36f4..00000000000 --- a/deployment/armada-bundle/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/deployment/armada-bundle/Chart.lock b/deployment/armada-bundle/Chart.lock deleted file mode 100644 index f9da1510436..00000000000 --- a/deployment/armada-bundle/Chart.lock +++ /dev/null @@ -1,33 +0,0 @@ -dependencies: -- name: redis-ha - repository: https://dandydeveloper.github.io/charts - version: 4.15.0 -- name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 11.1.27 -- name: armada-lookout-migration - repository: https://armadaproject.github.io/charts/ - version: v0.3.20 -- name: stan - repository: https://nats-io.github.io/k8s/helm/charts - version: 0.13.0 -- name: pulsar - repository: https://pulsar.apache.org/charts - version: 2.9.3 -- name: armada - repository: https://armadaproject.github.io/charts/ - version: v0.3.36 -- name: armada-executor - repository: https://armadaproject.github.io/charts/ - version: v0.3.36 -- name: armada-lookout - repository: https://armadaproject.github.io/charts/ - version: v0.3.36 -- name: armada-lookout-ingester - repository: https://armadaproject.github.io/charts/ - version: v0.3.36 -- name: executor-cluster-monitoring - repository: https://armadaproject.github.io/charts - version: v0.1.9 -digest: sha256:07796bf433ad7f1f17836c7032692d6dc617fee16a34a05a9050ed3671d8fe81 -generated: "2022-10-26T17:56:44.975573+02:00" diff --git a/deployment/armada-bundle/Chart.yaml b/deployment/armada-bundle/Chart.yaml deleted file mode 100644 index 6da7c06d0bf..00000000000 --- a/deployment/armada-bundle/Chart.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v2 -description: A helm chart which bundles Armada components -name: armada-bundle -version: 0.0.1 -appVersion: 0.0.0-latest -dependencies: - - name: redis-ha - version: 4.15.0 - repository: https://dandydeveloper.github.io/charts - condition: dependencies.redis-ha - - name: postgresql - version: 11.1.27 - repository: https://charts.bitnami.com/bitnami - condition: dependencies.postgresql - - name: armada-lookout-migration - version: v0.3.20 - repository: https://g-research.github.io/charts - condition: dependencies.armada-lookout-migration - - name: stan - version: 0.13.0 - repository: https://nats-io.github.io/k8s/helm/charts - condition: dependencies.stan - - name: pulsar - version: 2.9.3 - repository: https://pulsar.apache.org/charts - condition: dependencies.pulsar - - name: armada - version: v0.3.36 - repository: https://armadaproject.github.io/charts/ - condition: dependencies.armada-server - - name: armada-executor - version: v0.3.36 - repository: https://armadaproject.github.io/charts/ - condition: dependencies.armada-executor - - name: armada-lookout - version: v0.3.36 - repository: https://armadaproject.github.io/charts/ - condition: dependencies.armada-lookout - - name: armada-lookout-ingester - version: v0.3.36 - repository: https://armadaproject.github.io/charts/ - condition: dependencies.armada-lookout-ingester - - name: executor-cluster-monitoring - version: v0.1.9 - repository: https://armadaproject.github.io/charts - condition: dependencies.executor-cluster-monitoring diff --git a/deployment/armada-bundle/README.md b/deployment/armada-bundle/README.md deleted file mode 100644 index 24cacdade98..00000000000 --- a/deployment/armada-bundle/README.md +++ /dev/null @@ -1,131 +0,0 @@ -# armada-bundle - -![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![AppVersion: 0.0.0-latest](https://img.shields.io/badge/AppVersion-0.0.0--latest-informational?style=flat-square) - -A helm chart which bundles Armada components - -## Requirements - -| Repository | Name | Version | -|------------|------|---------| -| https://charts.bitnami.com/bitnami | postgresql | 11.1.27 | -| https://dandydeveloper.github.io/charts | redis-ha | 4.15.0 | -| https://armadaproject.github.io/charts/ | armada | v0.3.36 | -| https://armadaproject.github.io/charts/ | armada-executor | v0.3.36 | -| https://armadaproject.github.io/charts/ | armada-lookout | v0.3.36 | -| https://armadaproject.github.io/charts/ | armada-lookout-ingester | v0.3.36 | -| https://armadaproject.github.io/charts/ | armada-lookout-migration | v0.3.20 | -| https://armadaproject.github.io/charts | executor-cluster-monitoring | v0.1.9 | -| https://nats-io.github.io/k8s/helm/charts | stan | 0.13.0 | -| https://pulsar.apache.org/charts | pulsar | 2.9.3 | - -## Values - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| armada-executor.applicationConfig.apiConnection.armadaUrl | string | `"armada.default.svc.cluster.local:50051"` | URL of Armada Server gRPC endpoint | -| armada-executor.applicationConfig.apiConnection.forceNoTls | bool | `true` | Only to be used for development purposes and in cases where Armada server does not have a certificate | -| armada-executor.applicationConfig.kubernetes.minimumPodAge | string | `"0s"` | | -| armada-executor.image.repository | string | `"gresearchdev/armada-executor"` | | -| armada-executor.image.tag | string | `"v0.3.36"` | | -| armada-executor.nodeSelector | string | `"nil"` | | -| armada-executor.prometheus.enabled | bool | `true` | Toggle whether to create ServiceMonitor for Armada Executor | -| armada-lookout-ingester.applicationConfig.postgres.connMaxLifetime | string | `"30m"` | Postgres connection max lifetime | -| armada-lookout-ingester.applicationConfig.postgres.connection.dbname | string | `"postgres"` | Postgres database | -| armada-lookout-ingester.applicationConfig.postgres.connection.host | string | `"postgresql.armada.svc.cluster.local"` | Postgres host | -| armada-lookout-ingester.applicationConfig.postgres.connection.password | string | `"psw"` | Postgres user password | -| armada-lookout-ingester.applicationConfig.postgres.connection.port | int | `5432` | Postgres port | -| armada-lookout-ingester.applicationConfig.postgres.connection.sslmode | string | `"disable"` | Postgres SSL mode | -| armada-lookout-ingester.applicationConfig.postgres.connection.user | string | `"postgres"` | Postgres username | -| armada-lookout-ingester.applicationConfig.postgres.maxIdleConns | int | `25` | Postgres max idle connections | -| armada-lookout-ingester.applicationConfig.postgres.maxOpenConns | int | `100` | Postgres max open connections | -| armada-lookout-ingester.applicationConfig.pulsar.URL | string | `"pulsar://pulsar-broker.armada.svc.cluster.local:6650"` | Pulsar connection string | -| armada-lookout-ingester.applicationConfig.pulsar.enabled | bool | `true` | Toggle whether to connect to Pulsar | -| armada-lookout-ingester.applicationConfig.pulsar.jobsetEventsTopic | string | `"persistent://armada/armada/events"` | | -| armada-lookout-ingester.image.repository | string | `"gresearchdev/armada-lookout-ingester-dev"` | | -| armada-lookout-ingester.image.tag | string | `"88ea8f0b8124c7dbbb44f7c7315c0fca13655f18"` | | -| armada-lookout-migration.applicationConfig.postgres.connMaxLifetime | string | `"30m"` | Postgres connection max lifetime | -| armada-lookout-migration.applicationConfig.postgres.connection.dbname | string | `"postgres"` | Postgres database | -| armada-lookout-migration.applicationConfig.postgres.connection.host | string | `"postgresql.armada.svc.cluster.local"` | Postgres host | -| armada-lookout-migration.applicationConfig.postgres.connection.password | string | `"psw"` | Postgres user password | -| armada-lookout-migration.applicationConfig.postgres.connection.port | int | `5432` | Postgres port | -| armada-lookout-migration.applicationConfig.postgres.connection.user | string | `"postgres"` | Postgres username | -| armada-lookout-migration.applicationConfig.postgres.maxIdleConns | int | `25` | Postgres max idle connections | -| armada-lookout-migration.applicationConfig.postgres.maxOpenConns | int | `100` | Postgres max open connections | -| armada-lookout-migration.clusterIssuer | string | `"letsencrypt-dev"` | | -| armada-lookout-migration.image.tag | string | `"v0.3.36"` | | -| armada-lookout-migration.ingressClass | string | `"nginx"` | | -| armada-lookout-migration.prometheus.enabled | bool | `true` | | -| armada-lookout.applicationConfig.disableEventProcessing | bool | `true` | Armada does not require a streaming backend anymore so this options turns off processing via streaming backend (Jetstream, SNAT) | -| armada-lookout.applicationConfig.eventQueue | string | `"ArmadaLookoutEventProcessor"` | | -| armada-lookout.applicationConfig.postgres.connection.dbname | string | `"postgres"` | Postgres database | -| armada-lookout.applicationConfig.postgres.connection.host | string | `"postgresql.armada.svc.cluster.local"` | Postgres host | -| armada-lookout.applicationConfig.postgres.connection.password | string | `"psw"` | Postgres user password | -| armada-lookout.applicationConfig.postgres.connection.port | int | `5432` | Postgres port | -| armada-lookout.applicationConfig.postgres.connection.user | string | `"postgres"` | Postgres username | -| armada-lookout.clusterIssuer | string | `"dev-ca"` | ClusterIssuer from whom a Let's Encrypt certificate will be requested | -| armada-lookout.hostnames | list | `[]` | Ingress hostnames | -| armada-lookout.image.repository | string | `"gresearchdev/armada-lookout"` | | -| armada-lookout.image.tag | string | `"v0.3.36"` | | -| armada-lookout.ingress.annotations | object | `{}` | Ingress annotations | -| armada-lookout.ingress.labels | object | `{}` | Ingress labels | -| armada-lookout.ingressClass | string | `"nginx"` | Ingress class | -| armada-lookout.prometheus.enabled | bool | `true` | Toggle whether to create a ServiceMonitor for Lookout | -| armada.applicationConfig.auth | object | `{}` | Armada auth config | -| armada.applicationConfig.eventsNats.QueueGroup | string | `"ArmadaEventRedisProcessor"` | | -| armada.applicationConfig.eventsNats.clusterId | string | `"armada-cluster"` | STAN cluster ID | -| armada.applicationConfig.eventsNats.servers | list | `[]` | events STAN URIs | -| armada.applicationConfig.eventsNats.subject | string | `"ArmadaTest"` | | -| armada.applicationConfig.eventsNats.timeout | string | `"10s"` | | -| armada.applicationConfig.eventsRedis.addrs | list | `[]` | events Redis cluster instance URLs | -| armada.applicationConfig.eventsRedis.masterName | string | `"mymaster"` | | -| armada.applicationConfig.eventsRedis.poolSize | int | `1000` | | -| armada.applicationConfig.grpcPort | int | `50051` | | -| armada.applicationConfig.httpPort | int | `8080` | | -| armada.applicationConfig.pulsar.URL | string | `"pulsar://pulsar-broker.armada.svc.cluster.local:6650"` | Pulsar connection string | -| armada.applicationConfig.pulsar.enabled | bool | `true` | Toggle whether to connect to Pulsar | -| armada.applicationConfig.redis.addrs | list | `[]` | master Redis cluster instance URLs | -| armada.applicationConfig.redis.masterName | string | `"mymaster"` | | -| armada.applicationConfig.scheduling.defaultJobTolerations | list | `[]` | default node tolerations for Armada jobs | -| armada.applicationConfig.scheduling.probabilityOfUsingNewScheduler | int | `1` | | -| armada.clusterIssuer | string | `"dev-ca"` | ClusterIssuer from whom a Let's Encrypt certificate will be requested | -| armada.hostnames | list | `[]` | | -| armada.image.repository | string | `"gresearchdev/armada-server"` | | -| armada.image.tag | string | `"v0.3.36"` | | -| armada.ingressClass | string | `"nginx"` | Ingress class | -| armada.nodePort | int | `30000` | | -| armada.prometheus.enabled | bool | `true` | Toggle whether to create a ServiceMonitor for Armada Server | -| dependencies.armada-executor | bool | `true` | Toggle whether to install Armada Executor | -| dependencies.armada-lookout | bool | `true` | Toggle whether to install Armada Lookout UI | -| dependencies.armada-lookout-ingester | bool | `true` | Toggle whether to install Armada Lookout Ingester | -| dependencies.armada-lookout-migration | bool | `true` | Toggle whether to install Armada Lookout migrations | -| dependencies.armada-server | bool | `true` | Toggle whether to install Armada Server | -| dependencies.executor-cluster-monitoring | bool | `true` | Toggle whether to install executor cluster monitoring rules (NOTE: requires Prometheus CRDs) | -| dependencies.postgresql | bool | `true` | Toggle whether to install PostgreSQL | -| dependencies.pulsar | bool | `true` | Toggle whether to install Pulsar | -| dependencies.redis-ha | bool | `true` | Toggle whether to install Redis HA cluster | -| dependencies.stan | bool | `true` | Toggle whether to install Streaming NATS | -| executor-cluster-monitoring.additionalLabels.app | string | `"prometheus-operator"` | | -| executor-cluster-monitoring.additionalLabels.release | string | `"prometheus-operator"` | | -| executor-cluster-monitoring.interval | string | `"5s"` | | -| postgresql.auth.postgresPassword | string | `"psw"` | | -| postgresql.fullnameOverride | string | `"postgresql"` | | -| pulsar.armadaInit.adminPort | int | `8080` | Pulsar admin (REST) port | -| pulsar.armadaInit.brokerHost | string | `"pulsar-broker.armada.svc.cluster.local"` | Pulsar Broker host | -| pulsar.armadaInit.enabled | bool | `false` | Toggle whether to enable the job which creates necessary Pulsar resources needed by Armada | -| pulsar.armadaInit.image.repository | string | `"apachepulsar/pulsar"` | Pulsar image which contains pulsar-admin | -| pulsar.armadaInit.image.tag | string | `"2.10.2"` | Pulsar image tag | -| pulsar.armadaInit.port | int | `6650` | Pulsar application port | -| pulsar.armadaInit.protocol | string | `"http"` | Protocol used for connecting to Pulsar Broker host (either `http` or `https`) | -| pulsar.fullnameOverride | string | `"pulsar"` | Fullname override for Pulsar release | -| pulsar.grafana.service.type | string | `"ClusterIP"` | Pulsar Grafana kubernetes service type | -| pulsar.initialize | bool | `true` | | -| pulsar.proxy.service.type | string | `"ClusterIP"` | Pulsar Proxy kubernetes service type | -| redis-ha.fullnameOverride | string | `"redis-ha"` | | -| redis-ha.hardAntiAffinity | bool | `false` | | -| redis-ha.persistentVolume.enabled | bool | `false` | | -| stan.nameOverride | string | `"stan"` | | -| stan.stan.clusterID | string | `"armada-cluster"` | Streaming NATS Cluster ID (set during install and saved in the persistence backend) | - ----------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) diff --git a/deployment/armada-bundle/templates/pulsar-init-job.yaml b/deployment/armada-bundle/templates/pulsar-init-job.yaml deleted file mode 100644 index ccd2163ecf6..00000000000 --- a/deployment/armada-bundle/templates/pulsar-init-job.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.pulsar.armadaInit.enabled }} -apiVersion: batch/v1 -kind: Job -metadata: - name: pulsar-init -spec: - template: - spec: - initContainers: - - name: wait-for-pulsar - image: alpine:3.16 - command: - - /bin/sh - - -c - - | - echo "Waiting for Pulsar... ({{ .Values.pulsar.armadaInit.brokerHost }}:{{ .Values.pulsar.armadaInit.port }})" - - while ! nc -z {{ .Values.pulsar.armadaInit.brokerHost }} {{ .Values.pulsar.armadaInit.port }}; do - sleep 1 - done - - echo "Pulsar started!" - containers: - - name: init-pulsar - image: {{ .Values.pulsar.armadaInit.image.repository }}:{{ .Values.pulsar.armadaInit.image.tag }} - {{- $pulsarAdminUrl := printf "%s://%s:%s" .Values.pulsar.armadaInit.protocol .Values.pulsar.armadaInit.brokerHost (toString .Values.pulsar.armadaInit.adminPort) }} - command: - - sh - - -c - - | - echo -e "Initializing pulsar ({{ $pulsarAdminUrl }})" - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} tenants create armada - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} namespaces create armada/armada - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} topics delete-partitioned-topic persistent://armada/armada/events -f || true - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} topics create-partitioned-topic persistent://armada/armada/events -p 2 - - # Disable topic auto-creation to ensure an error is thrown on using the wrong topic - # (Pulsar automatically created the public tenant and default namespace). - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} namespaces set-auto-topic-creation public/default --disable - bin/pulsar-admin --admin-url {{ $pulsarAdminUrl }} namespaces set-auto-topic-creation armada/armada --disable - restartPolicy: Never - backoffLimit: 0 -{{- end }} diff --git a/deployment/armada-bundle/values.yaml b/deployment/armada-bundle/values.yaml deleted file mode 100644 index 74d975288c2..00000000000 --- a/deployment/armada-bundle/values.yaml +++ /dev/null @@ -1,267 +0,0 @@ -# Default values for armada-bundle. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -dependencies: - # -- Toggle whether to install Armada Server - armada-server: true - # -- Toggle whether to install Armada Executor - armada-executor: true - # -- Toggle whether to install Armada Lookout UI - armada-lookout: true - # -- Toggle whether to install Armada Lookout migrations - armada-lookout-migration: true - # -- Toggle whether to install Armada Lookout Ingester - armada-lookout-ingester: true - # -- Toggle whether to install Redis HA cluster - redis-ha: true - # -- Toggle whether to install Streaming NATS - stan: true - # -- Toggle whether to install Pulsar - pulsar: true - # -- Toggle whether to install executor cluster monitoring rules (NOTE: requires Prometheus CRDs) - executor-cluster-monitoring: true - # -- Toggle whether to install PostgreSQL - postgresql: true - -redis-ha: - fullnameOverride: redis-ha - hardAntiAffinity: false - persistentVolume: - enabled: false - -postgresql: - fullnameOverride: postgresql - auth: - postgresPassword: psw - -stan: - stan: - # -- Streaming NATS Cluster ID (set during install and saved in the persistence backend) - clusterID: "armada-cluster" - nameOverride: stan - -armada: - image: - repository: gresearchdev/armada-server - tag: v0.3.36 - # -- Ingress class - ingressClass: nginx - # -- ClusterIssuer from whom a Let's Encrypt certificate will be requested - clusterIssuer: dev-ca - hostnames: [] - - applicationConfig: - grpcPort: 50051 - httpPort: 8080 - # -- Armada auth config - auth: {} -# Here is an example auth config which disables basic auth and allows anybody to submit jobs -# NOTE: This setup should never be used in production environments -# basicAuth: -# enableAuthentication: false -# anonymousAuth: true -# permissionGroupMapping: -# submit_any_jobs: [ "everyone" ] -# create_queue: [ "everyone" ] -# delete_queue: [ "everyone" ] -# cancel_any_jobs: [ "everyone" ] -# reprioritize_any_jobs: [ "everyone" ] -# watch_all_events: [ "everyone" ] -# execute_jobs: [ "everyone" ] - redis: - masterName: "mymaster" - # -- master Redis cluster instance URLs - addrs: [] -# - "redis-ha-announce-0.armada.svc.cluster.local:26379" -# - "redis-ha-announce-1.armada.svc.cluster.local:26379" -# - "redis-ha-announce-2.armada.svc.cluster.local:26379" - eventsRedis: - masterName: "mymaster" - # -- events Redis cluster instance URLs - addrs: [] -# - "redis-ha-announce-0.armada.svc.cluster.local:26379" -# - "redis-ha-announce-1.armada.svc.cluster.local:26379" -# - "redis-ha-announce-2.armada.svc.cluster.local:26379" - poolSize: 1000 - eventsNats: - timeout: 10s - # -- events STAN URIs - servers: [] -# - "nats://stan.armada.svc.cluster.local:4222" - # -- STAN cluster ID - clusterId: "armada-cluster" - subject: "ArmadaTest" - QueueGroup: "ArmadaEventRedisProcessor" - scheduling: - probabilityOfUsingNewScheduler: 1 - # -- default node tolerations for Armada jobs - defaultJobTolerations: [] -# - key: armada.io/batch -# operator: Exists -# effect: NoSchedule - pulsar: - # -- Toggle whether to connect to Pulsar - enabled: true - # -- Pulsar connection string - URL: "pulsar://pulsar-broker.armada.svc.cluster.local:6650" - prometheus: - # -- Toggle whether to create a ServiceMonitor for Armada Server - enabled: true - - nodePort: 30000 - -armada-executor: - image: - repository: gresearchdev/armada-executor - tag: v0.3.36 - nodeSelector: nil - applicationConfig: - apiConnection: - # -- URL of Armada Server gRPC endpoint - armadaUrl: armada.default.svc.cluster.local:50051 - ## Please note that this setting is insecure - ## Do not use this setting in a production environment - ## This should only be used for the quickstart and local testing - # -- Only to be used for development purposes and in cases where Armada server does not have a certificate - forceNoTls: true - kubernetes: - minimumPodAge: 0s - - prometheus: - # -- Toggle whether to create ServiceMonitor for Armada Executor - enabled: true - -executor-cluster-monitoring: - additionalLabels: - app: prometheus-operator - release: prometheus-operator - - interval: 5s - -armada-lookout: - image: - repository: gresearchdev/armada-lookout - tag: v0.3.36 - # -- Ingress class - ingressClass: nginx - ingress: - # -- Ingress annotations - annotations: {} - # -- Ingress labels - labels: {} - # -- ClusterIssuer from whom a Let's Encrypt certificate will be requested - clusterIssuer: dev-ca - # -- Ingress hostnames - hostnames: [] - - prometheus: - # -- Toggle whether to create a ServiceMonitor for Lookout - enabled: true - - applicationConfig: - # -- Armada does not require a streaming backend anymore so this options turns off processing via streaming backend (Jetstream, SNAT) - disableEventProcessing: true - eventQueue: "ArmadaLookoutEventProcessor" - postgres: - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - -armada-lookout-migration: - image: - tag: v0.3.36 - ingressClass: nginx - clusterIssuer: letsencrypt-dev - - prometheus: - enabled: true - - applicationConfig: - postgres: - # -- Postgres max open connections - maxOpenConns: 100 - # -- Postgres max idle connections - maxIdleConns: 25 - # -- Postgres connection max lifetime - connMaxLifetime: 30m - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - -armada-lookout-ingester: - image: - repository: gresearchdev/armada-lookout-ingester-dev - tag: 88ea8f0b8124c7dbbb44f7c7315c0fca13655f18 - applicationConfig: - postgres: - # -- Postgres max open connections - maxOpenConns: 100 - # -- Postgres max idle connections - maxIdleConns: 25 - # -- Postgres connection max lifetime - connMaxLifetime: 30m - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - # -- Postgres SSL mode - sslmode: disable - pulsar: - # -- Toggle whether to connect to Pulsar - enabled: true - # -- Pulsar connection string - URL: "pulsar://pulsar-broker.armada.svc.cluster.local:6650" - jobsetEventsTopic: "persistent://armada/armada/events" - -pulsar: - armadaInit: - # -- Toggle whether to enable the job which creates necessary Pulsar resources needed by Armada - enabled: false - image: - # -- Pulsar image which contains pulsar-admin - repository: apachepulsar/pulsar - # -- Pulsar image tag - tag: 2.10.2 - # -- Pulsar Broker host - brokerHost: pulsar-broker.armada.svc.cluster.local - # -- Protocol used for connecting to Pulsar Broker host (either `http` or `https`) - protocol: http - # -- Pulsar admin (REST) port - adminPort: 8080 - # -- Pulsar application port - port: 6650 - proxy: - service: - # -- Pulsar Proxy kubernetes service type - type: ClusterIP - grafana: - service: - # -- Pulsar Grafana kubernetes service type - type: ClusterIP - initialize: true - # -- Fullname override for Pulsar release - fullnameOverride: pulsar diff --git a/deployment/armada-bundle/values/example.values.yaml b/deployment/armada-bundle/values/example.values.yaml deleted file mode 100644 index c96c3e8c70f..00000000000 --- a/deployment/armada-bundle/values/example.values.yaml +++ /dev/null @@ -1,273 +0,0 @@ -# Default values for armada-bundle. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. - -dependencies: - armada-server: true - armada-executor: true - armada-lookout: true - armada-lookout-migration: true - armada-lookout-ingester: true - redis-ha: true - stan: true - pulsar: true - executor-cluster-monitoring: true - postgresql: true - -redis-ha: - fullnameOverride: redis-ha - hardAntiAffinity: false - persistentVolume: - enabled: false - -postgresql: - fullnameOverride: postgresql - auth: - postgresPassword: psw - -stan: - stan: - # -- Streaming NATS Cluster ID (set during install and saved in the persistence backend) - clusterID: "armada-cluster" - nameOverride: stan - -kube-prometheus-stack: - alertmanager: - enabled: false - - prometheus: - prometheusSpec: - serviceMonitorSelectorNilUsesHelmValues: false - ruleSelectorNilUsesHelmValues: false - - grafana: - service: - type: NodePort - nodePort: 30001 - - prometheusOperator: - admissionWebhooks: - enabled: false - tls: - enabled: false - tlsProxy: - enabled: false - createCustomResource: false - -armada: - image: - repository: gresearchdev/armada-server - tag: v0.3.36 - # -- Ingress class - ingressClass: nginx - ingress: - labels: - # -- Ingress class as label, used usually as a workaround by external-dns as they currently do not support filtering by ingressClass field - kubernetes.io/ingress.class: nginx - # -- ClusterIssuer from whom a Let's Encrypt certificate will be requested - clusterIssuer: dev-ca - hostnames: [] - - applicationConfig: - grpcPort: 50051 - httpPort: 8080 - auth: - basicAuth: - enableAuthentication: false - anonymousAuth: true - permissionGroupMapping: - submit_any_jobs: [ "everyone" ] - create_queue: [ "everyone" ] - delete_queue: [ "everyone" ] - cancel_any_jobs: [ "everyone" ] - reprioritize_any_jobs: [ "everyone" ] - watch_all_events: [ "everyone" ] - execute_jobs: [ "everyone" ] - redis: - masterName: "mymaster" - addrs: - - "redis-ha-announce-0.armada.svc.cluster.local:26379" - - "redis-ha-announce-1.armada.svc.cluster.local:26379" - - "redis-ha-announce-2.armada.svc.cluster.local:26379" - eventsRedis: - masterName: "mymaster" - addrs: - - "redis-ha-announce-0.armada.svc.cluster.local:26379" - - "redis-ha-announce-1.armada.svc.cluster.local:26379" - - "redis-ha-announce-2.armada.svc.cluster.local:26379" - poolSize: 1000 - eventsNats: - timeout: 10s - servers: - - "nats://stan.armada.svc.cluster.local:4222" - clusterId: "armada-cluster" - subject: "ArmadaTest" - QueueGroup: "ArmadaEventRedisProcessor" - scheduling: - probabilityOfUsingNewScheduler: 1 - defaultJobTolerations: - - key: armada.io/batch - operator: Exists - effect: NoSchedule - pulsar: - # -- Toggle whether to connect to Pulsar - enabled: true - # -- Pulsar connection string - URL: "pulsar://pulsar-broker.armada.svc.cluster.local:6650" - prometheus: - # -- Toggle whether to create a ServiceMonitor for Armada Server - enabled: true - - nodePort: 30000 - -armada-executor: - image: - repository: gresearchdev/armada-executor - tag: v0.3.36 - nodeSelector: nil - applicationConfig: - apiConnection: - # -- URL of Armada Server gRPC endpoint - armadaUrl: armada.default.svc.cluster.local:50051 - ## Please note that this setting is insecure - ## Do not use this setting in a production environment - ## This should only be used for the quickstart and local testing - # -- Only to be used for development purposes and in cases where Armada server does not have a certificate - forceNoTls: true - kubernetes: - minimumPodAge: 0s - - prometheus: - # -- Toggle whether to create ServiceMonitor for Armada Executor - enabled: true - -executor-cluster-monitoring: - additionalLabels: - app: prometheus-operator - release: prometheus-operator - - interval: 5s - -armada-lookout: - image: - repository: gresearchdev/armada-lookout - tag: v0.3.36 - # -- Ingress class - ingressClass: nginx - ingress: - annotations: {} - labels: {} - # -- ClusterIssuer from whom a Let's Encrypt certificate will be requested - clusterIssuer: dev-ca - hostnames: [] - - prometheus: - # -- Toggle whether to create a ServiceMonitor for Lookout - enabled: true - - applicationConfig: - # -- Armada does not require a streaming backend anymore so this options turns off processing via streaming backend (Jetstream, SNAT) - disableEventProcessing: true - eventQueue: "ArmadaLookoutEventProcessor" - postgres: - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - -armada-lookout-migration: - image: - tag: v0.3.36 - ingressClass: nginx - clusterIssuer: letsencrypt-dev - - prometheus: - enabled: true - - applicationConfig: - postgres: - # -- Postgres max open connections - maxOpenConns: 100 - # -- Postgres max idle connections - maxIdleConns: 25 - # -- Postgres connection max lifetime - connMaxLifetime: 30m - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - -armada-lookout-ingester: - image: - repository: gresearchdev/armada-lookout-ingester-dev - tag: 88ea8f0b8124c7dbbb44f7c7315c0fca13655f18 - applicationConfig: - postgres: - # -- Postgres max open connections - maxOpenConns: 100 - # -- Postgres max idle connections - maxIdleConns: 25 - # -- Postgres connection max lifetime - connMaxLifetime: 30m - connection: - # -- Postgres host - host: postgresql.armada.svc.cluster.local - # -- Postgres port - port: 5432 - # -- Postgres username - user: postgres - # -- Postgres user password - password: psw - # -- Postgres database - dbname: postgres - # -- Postgres SSL mode - sslmode: disable - pulsar: - # -- Toggle whether to connect to Pulsar - enabled: true - # -- Pulsar connection string - URL: "pulsar://pulsar-broker.armada.svc.cluster.local:6650" - jobsetEventsTopic: "persistent://armada/armada/events" - -pulsar: - armadaInit: - # -- Toggle whether to enable the job which creates necessary Pulsar resources needed by Armada - enabled: false - image: - # -- Pulsar image which contains pulsar-admin - repository: apachepulsar/pulsar - # -- Pulsar image tag - tag: 2.10.2 - # -- Pulsar Broker host - brokerHost: pulsar-broker.armada.svc.cluster.local - # -- Protocol used for connecting to Pulsar Broker host (either `http` or `https`) - protocol: http - # -- Pulsar admin (REST) port - adminPort: 8080 - # -- Pulsar application port - port: 6650 - proxy: - service: - # -- Pulsar Proxy kubernetes service type - type: ClusterIP - grafana: - service: - # -- Pulsar Grafana kubernetes service type - type: ClusterIP - initialize: true - # -- Fullname override for Pulsar release - fullnameOverride: pulsar diff --git a/docs/demo.md b/docs/demo.md deleted file mode 100644 index 7b042944695..00000000000 --- a/docs/demo.md +++ /dev/null @@ -1,181 +0,0 @@ -# Armada Demo - -This guide will show you how to take a quick test drive of an Armada -instance already deployed to AWS EKS. - -## EKS - -The Armada UI (lookout) can be found at this URL: - -- [https://ui.demo.armadaproject.io](https://ui.demo.armadaproject.io) - -## Local prerequisites - -- Git -- Go 1.21 - -## Obtain the armada source -Clone [this](https://github.com/armadaproject/armada) repository: - -```bash -git clone https://github.com/armadaproject/armada.git -cd armada -``` -All commands are intended to be run from the root of the repository. - -## Armadactl configuration -Armadactl config files are structured as follows: -```yaml -currentContext: main # Default context to be used by Armadactl -contexts: - main: - armadaUrl: - execAuth: - cmd: - args: - - - test: - armadaUrl: - execAuth: - cmd: - args: - - -``` - -By default, armadactl assumes that a configuration file exists at `$HOME/.armadactl.yaml`. You can provide your own -config file by specifying `--config $CONFIG_FILE_PATH` when running armadactl. - -We also support a legacy armadactl config structure, although this will soon be deprecated: -```yaml -armadaUrl: -execAuth: - cmd: - args: - - -``` - -Under both structures, BasicAuth and various oidc auth methods are also supported. -See ApiConnectionDetails under pkg/client/connection.go for all supported auth methods. - -### Using contexts -It's quite common for Armada users to interact with multiple Armada instances, which we refer to as _contexts_. We have various -armadactl commands that allow users to get, set and view contexts. -```bash -armadactl config use-context test # Sets the context for future armadactl calls to "test" -armadactl config get-contexts # Gets all contexts defined in the current config -armadactl config current-context # Returns the current context -``` -Contexts are not supported with the legacy armadactl configuration. - -## Setup an easy-to-use alias -If you are on a Windows System, use a linux-supported terminal to run this command, for example [Git Bash](https://git-scm.com/downloads) or [Hyper](https://hyper.is/) -```bash -alias armadactl='go run cmd/armadactl/main.go' -``` - -## Create queues and jobs -Create queues, submit some jobs, and monitor progress: - -### Queue Creation -Use a unique name for the queue. Make sure you remember it for the next steps. -```bash -armadactl create queue $QUEUE_NAME --priority-factor 1 -armadactl create queue $QUEUE_NAME --priority-factor 2 -``` - -For queues created in this way, user and group owners of the queue have permissions to: -- submit jobs -- cancel jobs -- reprioritize jobs -- watch queue - -For more control, queues can be created via `armadactl create`, which allows for setting specific permission; see the following example. - -```bash -armadactl create -f ./docs/quickstart/queue-a.yaml -armadactl create -f ./docs/quickstart/queue-b.yaml -``` - -Make sure to manually edit both of these `yaml` files using a code or text editor before running the commands above. - -``` -name: $QUEUE_NAME -``` - -### Job Submission -``` -armadactl submit ./docs/quickstart/job-queue-a.yaml -armadactl submit ./docs/quickstart/job-queue-b.yaml -``` - -Make sure to manually edit both of these `yaml` files using a code or text editor before running the commands above. -``` -queue: $QUEUE_NAME -``` - -### Monitor Job Progress - -```bash -armadactl watch $QUEUE_NAME job-set-1 -``` -```bash -armadactl watch $QUEUE_NAME job-set-1 -``` - -Try submitting lots of jobs and see queues get built and processed: - -#### Windows (using Git Bash): - -Use a text editor of your choice. -Copy and paste the following lines into the text editor: -``` -#!/bin/bash - -for i in {1..50} -do - armadactl submit ./docs/quickstart/job-queue-a.yaml - armadactl submit ./docs/quickstart/job-queue-b.yaml -done -``` -Save the file with a ".sh" extension (e.g., myscript.sh) in the root directory of the project. -Open Git Bash, navigate to the project's directory using the 'cd' command, and then run the script by typing ./myscript.sh and pressing Enter. - -#### Linux: - -Open a text editor (e.g., Nano or Vim) in the terminal and create a new file by running: nano myscript.sh (replace "nano" with your preferred text editor if needed). -Copy and paste the script content from above into the text editor. -Save the file and exit the text editor. -Make the script file executable by running: chmod +x myscript.sh. -Run the script by typing ./myscript.sh in the terminal and pressing Enter. - -#### macOS: - -Follow the same steps as for Linux, as macOS uses the Bash shell by default. -With this approach, you create a shell script file that contains your multi-line script, and you can run it as a whole by executing the script file in the terminal. - -## Observing job progress - -CLI: - -```bash -$ armadactl watch queue-a job-set-1 -Watching job set job-set-1 -Nov 4 11:43:36 | Queued: 0, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobSubmittedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:36 | Queued: 1, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobQueuedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:36 | Queued: 1, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobSubmittedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:36 | Queued: 2, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobQueuedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:38 | Queued: 1, Leased: 1, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobLeasedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:38 | Queued: 0, Leased: 2, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobLeasedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:38 | Queued: 0, Leased: 1, Pending: 1, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobPendingEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:38 | Queued: 0, Leased: 0, Pending: 2, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobPendingEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:41 | Queued: 0, Leased: 0, Pending: 1, Running: 1, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobRunningEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:41 | Queued: 0, Leased: 0, Pending: 0, Running: 2, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobRunningEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:44:17 | Queued: 0, Leased: 0, Pending: 0, Running: 1, Succeeded: 1, Failed: 0, Cancelled: 0 | event: *api.JobSucceededEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:44:26 | Queued: 0, Leased: 0, Pending: 0, Running: 0, Succeeded: 2, Failed: 0, Cancelled: 0 | event: *api.JobSucceededEvent, job id: 01drv3mey2mzmayf50631tzp9m -``` - -Web UI: - -Open [https://ui.demo.armadaproject.io](https://ui.demo.armadaproject.io) in your browser. - -![Lookout UI](./quickstart/img/lookout.png "Lookout UI") diff --git a/docs/developer/aws-ec2.md b/docs/developer/aws-ec2.md deleted file mode 100644 index 66ffdbe468e..00000000000 --- a/docs/developer/aws-ec2.md +++ /dev/null @@ -1,236 +0,0 @@ -# EC2 Developer Setup - -## Background - -For development, you might want to set up an Amazon EC2 instance as the resource requirements for Armada are substantial. A typical Armada installation requires a system with at least 16GB of memory to perform well. Running Armada on a laptop made before ~2017 will typically eat battery life and result in a slower UI. - -Note: As of June 2022, not all Armada dependencies reliably build on a Mac M1 using standard package management. So if you have an M1 Mac, working on EC2 or another external server is your best bet. - -## Instructions - -- We suggest a t3.xlarge instance from aws ec2 with AmazonLinux as the OS. 16 GB of memory is suggested. -- During selection of instance, Add a large volume to your ec2 instance. 100 gb of storage is recommended. -- When selecting the instance, you will have the opportunity to choose a security group. You may need to make a new one. Be sure to add a rule allowing inbound communication on port 22 so that you can access your server via SSH. We recommend that you restrict access to the IP address from which you access the Internet, or a small CIDR block containing it. - -If you want to use your browser to access Armada Lookout UI or other web-based interfaces, you will also need to grant access to their respective ports. For added security, consider using an [SSH tunnel](https://www.ssh.com/academy/ssh/tunneling/example) from your local machine to your development server instead of opening those ports. You can add LocalForward to your ssh config: `LocalForward 4000 localhost:3000` - -- ### Install [Docker](https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/) - -The procedure to install Docker on AMI 2 (Amazon Linux 2) running on either EC2 or Lightsail instance is as follows: - -1. Login into remote AWS server using the ssh command: - -``` -ssh ec2-user@ec2-ip-address-dns-name-here -``` - -2. Apply pending updates using the yum command: - -``` -sudo yum update -``` - -3. Search for Docker package: - -``` -sudo yum search docker -``` - -4. Get version information: - -``` -sudo yum info docker -``` -

- -

- -5. Install docker, run: - -``` -sudo yum install docker -``` - -6. Add group membership for the default ec2-user so you can run all docker commands without using the sudo command: - -``` -sudo usermod -a -G docker ec2-user -id ec2-user -# Reload a Linux user's group assignments to docker w/o logout -newgrp docker -``` - - -- ### Install [docker-compose](https://www.cyberciti.biz/faq/how-to-install-docker-on-amazon-linux-2/) - -```bash -$ cd $HOME/.docker -$ mkdir cli-plugins -$ cd cli-plugins -$ curl -SL https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-linux-x86_64 -o docker-compose -$ chmod 755 docker-compose -``` - -Then verify it with: - -```bash -docker-compose version -``` - -- ### Getting the [Docker Compose Plugin](https://docs.docker.com/compose/install/linux/#install-the-plugin-manually) - -Armadas setup assumes You have the docker compose plugin installed. If you do not have it installed, you can use the following guide: - -* https://docs.docker.com/compose/install/linux/#install-the-plugin-manually - -Then test it with: - -```bash -docker compose version -``` - - -- ### Install [Go](https://go.dev/doc/install) - -ssh into your EC2 instance, become root and download the go package from [golang.org](https://go.dev/doc/install). - -1. Extract the archive you downloaded into /usr/local, creating a Go tree in /usr/local/go with the following command: - -``` -rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.1.linux-amd64.tar.gz -``` - -2. Configure .bashrc - -Switch back to ec2-user and add the following line to your ~/.bashrc file - -``` -export PATH=$PATH:/usr/local/go/bin -``` - -3. Configure go Environment - -Add the following lines to your ~/.bashrc file as well, also create a golang folder under /home/ec2-user. - -``` -# Go envs -export GOVERSION=go1.21.1 -export GO_INSTALL_DIR=/usr/local/go -export GOROOT=$GO_INSTALL_DIR -export GOPATH=/home/ec2-user/golang -export PATH=$GOROOT/bin:$GOPATH/bin:$PATH -export GO111MODULE="on" -export GOSUMDB=off -``` - -4. Test go - -Verify that you’ve installed Go by opening a command prompt and typing the following command: - -``` -go version -go version go1.21.1 linux/amd64 -``` - -- ### Install [Kind](https://dev.to/rajitpaul_savesoil/setup-kind-kubernetes-in-docker-on-linux-3kbd) - -1. Install Kind - -``` -go install sigs.k8s.io/kind@v0.11.1 -# You can replace v0.11.1 with the latest stable kind version -``` - -2. Move the KinD Binary to /usr/local/bin - -``` -- You can find the kind binary inside the directory go/bin -- Move it to /usr/local/bin - mv go/bin/kind /usr/local/bin -- Make sure you have a path setup for /usr/local/bin -``` - -- ### Install [kubectl](https://dev.to/rajitpaul_savesoil/setup-kind-kubernetes-in-docker-on-linux-3kbd) - -1. Install Latest Version of Kubectl: - -``` -curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -chmod +x kubectl -mv kubectl /usr/local/bin -``` - -- ### Install [helm](https://helm.sh/docs/intro/install/) - -1. Install helm: - -``` -curl -sSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash -``` - -2. We can verify the version - -``` -helm version --short -``` - -- ### Install [python3 (>= 3.7)](https://www.geeksforgeeks.org/how-to-install-python3-on-aws-ec2/) - -1. Check if Python is already installed or not on our AWS EC2. - -``` -python --version -``` - -

- -

- -2. At first update, Ubuntu packages by using the following command. - -``` -sudo apt update -``` - -

- -

- -3. If Python3 is not installed on your AWS EC2, then install Python3 using the following command. - -``` -sudo apt-get install python3.7 -``` - -4. We have successfully installed Python3 on AWS EC2, to check if Python3 is successfully installed or not, verify using the following command. - -``` -python3 --version -``` - -- ### Install .NET for [linux](https://docs.microsoft.com/en-us/dotnet/core/install/linux-centos) - -1. Before you install .NET, run the following commands to add the Microsoft package signing key to your list of trusted keys and add the Microsoft package repository. Open a terminal and run the following commands: - -``` -sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm -``` - -2. Install the SDK - -``` -sudo yum install dotnet-sdk-7.0 -``` - -3. Install the runtime - -``` -sudo yum install aspnetcore-runtime-7.0 -``` - -- ### We suggest using the [remote code extension](https://code.visualstudio.com/docs/remote/ssh) for VS Code if that is your IDE of choice. - -

- -

- -- ### Please see [Our Developer Docs](../developer.md) for more information on how to get started with the codebase. diff --git a/docs/developer/etcd-localdev.md b/docs/developer/etcd-localdev.md deleted file mode 100644 index fe8c2e309a8..00000000000 --- a/docs/developer/etcd-localdev.md +++ /dev/null @@ -1,74 +0,0 @@ -# Inspect and Debugging etcd in Localdev setup - -When developing or testing Armada in the Localdev setup, it's sometimes helpful -to directly query the etcd database to gather various statistics. However, by -default, the `kind` tool (for running Kubernetes clusters inside a local Docker -side) does not expose the etcd interface for direct querying. The following -steps give a solution for querying an etcd instance running inside of `kind`. - - -First, verify the running nodes and podes. -```bash -$ kubectl get nodes -A -NAME STATUS ROLES AGE VERSION -armada-test-control-plane Ready control-plane 78m v1.24.7 -armada-test-worker Ready 77m v1.24.7 - -$ kubectl get pods -A -NAMESPACE NAME READY STATUS RESTARTS AGE -ingress-nginx ingress-nginx-admission-create-9xnpn 0/1 Completed 0 78m -ingress-nginx ingress-nginx-admission-patch-phkgm 0/1 Completed 1 78m -ingress-nginx ingress-nginx-controller-646df5f698-zbgqz 1/1 Running 0 78m -kube-system coredns-6d4b75cb6d-9z87w 1/1 Running 0 79m -kube-system coredns-6d4b75cb6d-flz4r 1/1 Running 0 79m -kube-system etcd-armada-test-control-plane 1/1 Running 0 79m -kube-system kindnet-nx952 1/1 Running 0 79m -kube-system kindnet-rtqkc 1/1 Running 0 79m -kube-system kube-apiserver-armada-test-control-plane 1/1 Running 0 79m -kube-system kube-controller-manager-armada-test-control-plane 1/1 Running 0 79m -kube-system kube-proxy-cwl2r 1/1 Running 0 79m -kube-system kube-proxy-wjqft 1/1 Running 0 79m -kube-system kube-scheduler-armada-test-control-plane 1/1 Running 0 79m -local-path-storage local-path-provisioner-6b84c5c67f-22m8m 1/1 Running 0 79m -``` -You should see an etcd control plane pod in the list of pods. - -Copy the etcdclient deployment YAML into the cluster control plane node: - -```bash -$ docker cp developer/config/etcdclient.yaml armada-test-control-plane:/ -``` - -Then, open a shell in the control plane node: -```bash -$ docker exec -it -u 0 --privileged armada-test-control-plane /bin/bash -``` - -In the container shell, move the deployment YAML file to the Kubernetes deployments source -directory. Kubernetes (Kind) will notice the file's appearance and will deploy -the new pod. -```bash -root@armada-test-control-plane:/# mv etcdclient.yaml /etc/kubernetes/manifests/ -root@armada-test-control-plane:/# exit -$ kubectl get pods -A -``` -You should see an etcdclient pod running. - -Open a shell in the new etcdclient utility pod, and start using `etcdctl` to query etcd. -```bash -$ kubectl exec -n kube-system -it etcdclient-armada-test-control-plane -- sh -/ # etcdctl endpoint status -w table -+-------------------------+------------------+---------+---------+-----------+-----------+------------+ -| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX | -+-------------------------+------------------+---------+---------+-----------+-----------+------------+ -| https://172.19.0.2:2379 | d7380397c3ec4b90 | 3.5.3 | 3.9 MB | true | 2 | 16727 | -+-------------------------+------------------+---------+---------+-----------+-----------+------------+ -/ # -/ # exit -``` -At this point, you can use `etcdctl` to query etcd for key-value pairs, get the health and/or metrics -of the etcd server. - -## References - -https://mauilion.dev/posts/etcdclient/ diff --git a/docs/developer/manual-localdev.md b/docs/developer/manual-localdev.md deleted file mode 100644 index 24321f740d6..00000000000 --- a/docs/developer/manual-localdev.md +++ /dev/null @@ -1,75 +0,0 @@ -# Manual Local Development - -Here, we give an overview of a development setup for Armada that gives users full control over the Armada components and dependencies. - -Before starting, please ensure you have installed [Go](https://go.dev/doc/install) (version 1.21 or later), gcc (for Windows, see, e.g., [tdm-gcc](https://jmeubank.github.io/tdm-gcc/)), [mage](https://magefile.org/), [docker](https://docs.docker.com/get-docker/), [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl), and, if you need to compile `.proto` files, [protoc](https://github.com/protocolbuffers/protobuf/releases). - -For a full list of mage commands, run `mage -l`. - -## Setup - -### Note for Arm/M1 Mac Users - -You will need to set the `PULSAR_IMAGE` enviromental variable to an arm64 image. - -We provide an optimised image for this purpose: - -```bash -export PULSAR_IMAGE=richgross/pulsar:2.11.0 -``` - -```bash -# Download Go dependencies. -go mod tidy - -# Install necessary tooling. -mage BootstrapTools - -# Compile .pb.go files from .proto files -# (only necessary after changing a .proto file). -mage proto -mage dotnet - -# Build the Docker images containing all Armada components. -# Only the main "bundle" is needed for quickly testing Armada. -mage buildDockers "bundle,lookout-bundle,jobservice" - -# Setup up a kind (i.e., Kubernetes-in-Docker) cluster; see -# https://kind.sigs.k8s.io/ for details. -mage Kind - -# Start necessary dependencies. -# Verify that dependencies started successfully -# (check that Pulsar has fully started as it is quite slow (~ 1min )). -mage StartDependencies && mage checkForPulsarRunning - -# Start the Armada server and executor. -# Alternatively, run the Armada server and executor directly on the host, -# e.g., through your IDE; see below for details. -docker compose up -d server executor-legacy - -# Wait for Armada to come online -mage checkForArmadaRunning -``` - -Run the Armada test suite against the local environment to verify that it is working correctly. -```bash -# Create an Armada queue to submit jobs to. -go run cmd/armadactl/main.go create queue e2e-test-queue - -# To allow Ingress tests to pass -export ARMADA_EXECUTOR_INGRESS_URL="http://localhost" -export ARMADA_EXECUTOR_INGRESS_PORT=5001 - -# Run the Armada test suite against the local environment. -go run cmd/testsuite/main.go test --tests "testsuite/testcases/basic/*" --junit junit.xml -``` - -Tear down the local environment using the following: -```bash -# Stop Armada components and dependencies. -docker compose down - -# Tear down the kind cluster. -mage KindTeardown -``` diff --git a/docs/developer/ubuntu-setup.md b/docs/developer/ubuntu-setup.md deleted file mode 100644 index db3733c6e50..00000000000 --- a/docs/developer/ubuntu-setup.md +++ /dev/null @@ -1,173 +0,0 @@ -# Setting up an Ubuntu Linux instance for Armada development - -## Introduction - -This document is a list of the steps, packages, and tweaks that need to be done to get an Ubuntu Linux -instance running, with all the tools needed for Armada development and testing. - -The packages and steps were verified on an AWS EC2 instance (type t3.xlarge, 4 vcpu, 16GB RAM, -150GB EBS disk), but should be essentially the same on any comparable hardware system. - -### Install Ubuntu Linux - -Install Ubuntu Linux 22.04 (later versions may work as well). The default package set should -work. If you are setting up a new AWS EC2 instance, the default Ubuntu 22.04 image works well. - -When installing, ensure that the network configuration allows: -- SSH traffic from your client IP(s) -- HTTP traffic -- HTTPS traffic - -Apply all recent updates: -``` -$ sudo apt update -$ sudo apt upgrade -``` -You will likely need to reboot after applying the updates: -``` -$ sudo shutdown -r now -``` -After logging in, clean up any old, unused packages: -``` -$ sudo apt autoremove -``` - -AWS usually creates new EC2 instances with a very small root partion (8GB), which will quickly -fill up when using containers, or doing any serious development. Creating a new, large EBS volume, and -attaching it to the instance, will give a system usable for container work. - -First, provision an EBS volume in the AWS Console - of at least 150GB, or more - and attach it to -the instance. You will need to create the EBS volume in the same availability zone as the EC2 -instance - you can find the latter's AZ by clicking on the 'Networking' tab in the details page -for the instance, and you should see the Availabilty Zone listed in that panel. Once you've created -the volume, attach it to the instance. - -Then, format a filesystem on the volume and mount it. First, determine what block device the -parition is on, by running the `lsblk` comand. There should be a line where the TYPE is 'disk' -and the size matches the size you specified when creating the volume - e.g. -``` -nvme1n1 259:4 0 150G 0 disk -``` -Create a filesystem on that device by running `mkfs`: -``` -$ sudo mkfs -t ext4 /dev/nvme1n1 -``` -Then set a label on the partition - here, we will give it a label of 'VOL1': -``` -$ sudo e2label /dev/nvme1n1 VOL1 -``` -Create the mount-point directory: -``` -$ sudo mkdir /vol1 -``` -Add the following line to the end of `/etc/fstab`, so it will be mounted upon reboot: -``` -LABEL=VOL1 /vol1 ext4 defaults 0 2 -``` -Then mount it by doing `sudo mount -a`, and confirm the available space by running `df -h` - the `/vol1` -filesystem should be listed. - -### Install Language/Tool Packages - -Install several development packages that aren't installed by default in the base system: -``` -$ sudo apt install gcc make unzip -``` - -### Install Go, Protobuffers, and kubectl tools -Install the Go compiler and associated tools. Currently, the latest version is 1.21.1, but there may -be newer versions: - -``` -$ curl --location -O https://go.dev/dl/go1.21.1.linux-amd64.tar.gz -$ sudo tar -C /usr/local -xzvf go1.21.1.linux-amd64.tar.gl -$ echo 'export PATH=$PATH:/usr/local/go/bin' > go.sh -$ sudo cp go.sh /etc/profile.d/ -``` -Then, log out and back in again, then run `go version` to verify your path is now correct. - -Install protoc: -``` -$ curl -O --location https://github.com/protocolbuffers/protobuf/releases/download/v23.3/protoc-23.3-linux-x86_64.zip -$ cd /usr/local && sudo unzip ~/protoc-23.3-linux-x86_64.zip -$ cd ~ -$ type protoc -``` - -Install kubectl: -``` -$ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -$ sudo cp kubectl /usr/local/bin -$ sudo chmod 755 /usr/local/bin/kubectl -$ kubectl version -``` - -### Install Docker - -Warning: do not install Docker as provided by the `docker.io` and other packages in the Ubuntu base -packages repository - the version of Docker they provide is out-of-date. - -Instead, follow the instructions for installing Docker on Ubuntu at https://docs.docker.com/engine/install/ubuntu/ . -Specifically, follow the listed steps for installing using an apt repository, and install a recent version. - -*WARNING*: at the time of this writing, there is a known release of the Docker Engine that causes Armada -localdev setups to fail, due to container image loading errors. The broken release is -`5:25.0.0-1~ubuntu.22.04~jammy` (for Ubuntu 22.04) - it may be referenced as Docker Engine v25.0.0. The -most recent prior major version at this time - v24.0.7 - has been verified to work correctly for Armada -development - `5:24.0.7-1~ubuntu.22.04~jammy`. In the docs sub-section *2.0 Install the Docker pages*, click -on the *Specific version* tab for details and instructions how to install an earlier release. However, -it's expected that Docker will have a newer version (higher than 25.0.0) that will fix this issue; please -consult the Docker release notes. - -### Relocate Docker storage directory to secondary volume - -Since Docker can use a lot of filesystem space, the directory where it stores container images, logs, -and other datafiles should be relocated to the separate, larger non-root volume on the system, so that -the root filesystem does not fill up. - -Stop the Docker daemon(s) and copy the existing data directory to the new location: -``` -$ sudo systemctl stop docker -$ ps ax | grep -i docker # no Docker processes should be shown - -$ sudo rsync -av /var/lib/docker /vol1/ -$ sudo rm -rf /var/lib/docker -$ sudo ln -s /vol1/docker /var/lib/docker -``` -Then restart Docker and verify that it's working again: -``` -$ sudo systemctl start docker -$ sudo docker ps -$ sudo docker run hello-world -``` - -### Create user accounts, verify docker access - -First, make a home directory parent in the new larger filesystem: -``` -$ sudo mkdir /vol1/home -``` -Then, for each user to be added, run the following steps - we will be using the account named 'testuser' here. -First, create the account and their home directory. -``` -$ sudo adduser --shell /bin/bash --gecos 'Test User' --home /vol1/home/testuser testuser -``` -Set up their $HOME/.ssh directory and add their SSH public-key: -``` -$ sudo mkdir /vol1/home/testuser/.ssh -$ sudo vim /vol1/home/testuser/.ssh/authorized_keys -# In the editor, add the SSH public key string that the user has given you, save the file and exit -$ sudo chmod 600 /vol1/home/testuser/.ssh/authorized_keys -$ sudo chmod 700 /vol1/home/testuser/.ssh -$ sudo chown -R testuser:testuser /vol1/home/testuser/.ssh -``` -Finally, add them to the `docker` group so they can run Docker commands without `sudo` access: -``` -$ sudo gpasswd -a testuser docker -``` -**sudo Access (OPTIONAL)** - -If you want to give the new user `sudo` privileges, run the following command: -``` -$ sudo gpasswd -a testuser sudo -``` diff --git a/docs/local/armadactl.sh b/docs/local/armadactl.sh deleted file mode 100755 index a5fe56ff5cd..00000000000 --- a/docs/local/armadactl.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -ex - -echo "Downloading armadactl for your platform" - -# Determine Platform -SYSTEM=$(uname | sed 's/MINGW.*/windows/' | tr A-Z a-z) -if [ "$SYSTEM" = "windows" ]; then - ARCHIVE_TYPE=zip - UNARCHIVE="zcat > armadactl.exe" -else - ARCHIVE_TYPE=tar.gz - UNARCHIVE="tar xzf -" -fi - -# Find the latest Armada version -LATEST_GH_URL=$(curl -fsSLI -o /dev/null -w %{url_effective} https://github.com/armadaproject/armada/releases/latest) - -# Hard version set required until https://github.com/armadaproject/armada/pull/2384 is released -# ARMADA_VERSION=${LATEST_GH_URL##*/} -ARMADA_VERSION="v0.3.61" -ARMADACTL_URL="https://github.com/armadaproject/armada/releases/download/$ARMADA_VERSION/armadactl-$ARMADA_VERSION-$SYSTEM-amd64.$ARCHIVE_TYPE" - -# Download and untar/unzip armadactl -if curl -sL $ARMADACTL_URL | sh -c "$UNARCHIVE" ; then - echo "armadactl downloaded successfully" - - # Move armadactl binary to a directory in user's PATH - TARGET_DIR="$HOME/bin" # Change this to the desired target directory in your user's home - mkdir -p "$TARGET_DIR" - cp armadactl "$TARGET_DIR/" - export PATH="$TARGET_DIR:$PATH" - - echo "armadactl is now available on your PATH" - -else - echo "Something is amiss!" - echo "Please visit:" - echo " - https://github.com/armadaproject/armada/releases/latest" - echo "to find the latest armadactl binary for your platform" -fi diff --git a/docs/local/destroy.sh b/docs/local/destroy.sh deleted file mode 100755 index 8b78862c58e..00000000000 --- a/docs/local/destroy.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -printf "\n*******************************************************\n" -printf "Destroying Armada server cluster" -printf "\n*******************************************************\n" -kind delete cluster --name quickstart-armada-server -printf "\033[1mdone\033[0m" -printf "\n*******************************************************\n" -printf "Destroying first Armada executor cluster" -printf "\n*******************************************************\n" -kind delete cluster --name quickstart-armada-executor-0 -printf "\033[1mdone\033[0m" -printf "\n*******************************************************\n" -printf "Destroying second Armada executor cluster" -printf "\n*******************************************************\n" -kind delete cluster --name quickstart-armada-executor-1 -printf "\033[1mdone\033[0m\n" \ No newline at end of file diff --git a/docs/local/setup.sh b/docs/local/setup.sh deleted file mode 100755 index 93d5aa92e46..00000000000 --- a/docs/local/setup.sh +++ /dev/null @@ -1,165 +0,0 @@ -#!/bin/sh -ex - -KIND_IMG="kindest/node:v1.21.10" -CHART_VERSION_ARMADA="v0.3.20" -CHART_VERSION_ARMADA_EXECUTOR_MONITORING="v0.1.9" -CHART_VERSION_KUBE_PROMETHEUS_STACK="13.0.0" -CHART_VERSION_NATS="0.13.0" -CHART_VERSION_POSTGRES="12.4.2" -CHART_VERSION_PULSAR="2.9.4" -CHART_VERSION_REDIS="4.22.3" - -printf "\n*******************************************************\n" -printf "Running script which will deploy a local Armada cluster" -printf "\n*******************************************************\n" - -##################################################### -# HELM CONFIGURATION # -##################################################### -printf "\n*******************************************************\n" -printf "Registering required helm repositories ..." -printf "\n*******************************************************\n" -helm repo add dandydev https://dandydeveloper.github.io/charts -helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -helm repo add nats https://nats-io.github.io/k8s/helm/charts -helm repo add bitnami https://charts.bitnami.com/bitnami -helm repo add gresearch https://g-research.github.io/charts -helm repo add apache https://pulsar.apache.org/charts -helm repo update - -##################################################### -# ARMADA SERVER # -##################################################### -printf "\n*******************************************************\n" -printf "Deploying Armada server ..." -printf "\n*******************************************************\n" -if kind delete cluster --name quickstart-armada-server; then - printf "Deleting existing quickstart-armada-server ..." - -fi -kind create cluster --name quickstart-armada-server --config ./docs/quickstart/kind/kind-config-server.yaml --image $KIND_IMG - -# Set cluster as current context -kind export kubeconfig --name=quickstart-armada-server - -# Install Redis -printf "\nStarting Redis ...\n" -helm install redis dandydev/redis-ha --version $CHART_VERSION_REDIS -f docs/quickstart/helm/values-redis.yaml - -# Install nats-streaming -printf "\nStarting NATS ...\n" -helm install nats nats/stan --version $CHART_VERSION_NATS --wait - -# Install Apache Pulsar -printf "\nStarting Pulsar ...\n" -helm install pulsar apache/pulsar --version $CHART_VERSION_PULSAR -f docs/quickstart/helm/values-pulsar.yaml - -# Install Prometheus -printf "\nStarting Prometheus ...\n" -helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version $CHART_VERSION_KUBE_PROMETHEUS_STACK -f docs/quickstart/helm/values-server-prometheus.yaml - -# Install Armada server -printf "\nStarting Armada server ...\n" -helm install armada-server gresearch/armada --version $CHART_VERSION_ARMADA -f ./docs/quickstart/helm/values-server.yaml - -# Get server IP for executors -SERVER_IP=$(kubectl get nodes quickstart-armada-server-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}') -##################################################### - -##################################################### -# ARMADA EXECUTOR 1 # -##################################################### -printf "\n*******************************************************\n" -printf "Deploying first Armada executor cluster ..." -printf "\n*******************************************************\n" -if kind delete cluster --name quickstart-armada-executor-0; then - printf "Deleting existing quickstart-armada-executor-0 cluster ..." - -fi -kind create cluster --name quickstart-armada-executor-0 --config ./docs/quickstart/kind/kind-config-executor.yaml --image $KIND_IMG - -# Set cluster as current context -kind export kubeconfig --name=quickstart-armada-executor-0 - -# Install Prometheus -helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version $CHART_VERSION_KUBE_PROMETHEUS_STACK -f docs/quickstart/helm/values-executor-prometheus.yaml - -# Install executor -helm install armada-executor gresearch/armada-executor --version $CHART_VERSION_ARMADA --set applicationConfig.apiConnection.armadaUrl="$SERVER_IP:30000" -f docs/quickstart/helm/values-executor.yaml -helm install armada-executor-cluster-monitoring gresearch/executor-cluster-monitoring --version $CHART_VERSION_ARMADA_EXECUTOR_MONITORING -f docs/quickstart/helm/values-executor-cluster-monitoring.yaml - -# Get executor IP for Grafana -EXECUTOR_0_IP=$(kubectl get nodes quickstart-armada-executor-0-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}') -##################################################### - -##################################################### -# ARMADA EXECUTOR 2 # -##################################################### -printf "\n*******************************************************\n" -printf "Deploying second Armada executor cluster ..." -printf "\n*******************************************************\n" -if kind delete cluster --name quickstart-armada-executor-1; then - printf "Deleting existing quickstart-armada-executor-1 cluster ..." - -fi -kind create cluster --name quickstart-armada-executor-1 --config ./docs/quickstart/kind/kind-config-executor.yaml --image $KIND_IMG - -# Set cluster as current context -kind export kubeconfig --name=quickstart-armada-executor-1 - -# Install Prometheus -helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --version $CHART_VERSION_KUBE_PROMETHEUS_STACK -f docs/quickstart/helm/values-executor-prometheus.yaml - -# Install executor -helm install armada-executor gresearch/armada-executor --version $CHART_VERSION_ARMADA --set applicationConfig.apiConnection.armadaUrl="$SERVER_IP:30000" -f docs/quickstart/helm/values-executor.yaml -helm install armada-executor-cluster-monitoring gresearch/executor-cluster-monitoring --version $CHART_VERSION_ARMADA_EXECUTOR_MONITORING -f docs/quickstart/helm/values-executor-cluster-monitoring.yaml - -# Get executor IP for Grafana -EXECUTOR_1_IP=$(kubectl get nodes quickstart-armada-executor-1-worker -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}') -##################################################### - -##################################################### -# ARMADA LOOKOUT # -##################################################### -printf "\n*******************************************************\n" -printf "Deploying Armada Lookout UI ..." -printf "\n*******************************************************\n" -kind export kubeconfig --name=quickstart-armada-server - -# Install postgres -helm install postgres bitnami/postgresql --version $CHART_VERSION_POSTGRES --wait --set auth.postgresPassword=psw - -# Run database migration -helm install lookout-migration gresearch/armada-lookout-migration --version $CHART_VERSION_ARMADA --wait -f docs/quickstart/helm/values-lookout.yaml - -# Install Armada Lookout -helm install lookout gresearch/armada-lookout --version $CHART_VERSION_ARMADA -f docs/quickstart/helm/values-lookout.yaml -##################################################### - -##################################################### -# GRAFANA CONFIG # -##################################################### -printf "\n*******************************************************\n" -printf "Configuring Grafana dashboard for Armada ..." -printf "\n*******************************************************\n" -curl -X POST -i http://admin:prom-operator@localhost:30001/api/datasources -H "Content-Type: application/json" -d '{"name":"cluster-0","type":"prometheus","url":"http://'$EXECUTOR_0_IP':30001","access":"proxy","basicAuth":false}' -curl -X POST -i http://admin:prom-operator@localhost:30001/api/datasources -H "Content-Type: application/json" -d '{"name":"cluster-1","type":"prometheus","url":"http://'$EXECUTOR_1_IP':30001","access":"proxy","basicAuth":false}' -curl -X POST -i http://admin:prom-operator@localhost:30001/api/dashboards/import --data-binary @./docs/quickstart/grafana-armada-dashboard.json -H "Content-Type: application/json" - -printf "\n*******************************************************\n" -printf "Finished deploying local Armada cluster" -printf "\n*******************************************************\n" - -bs="\033[1m" -be="\033[0m" -printf "\nArmada Lookout UI can be accessed by doing the following:" -printf "\n\t* type %bkubectl port-forward svc/armada-lookout 8080:8080%b in your terminal" "$bs" "$be" -printf "\n\t* open %bhttp://localhost:8080%b in your browser\n" "$bs" "$be" - -printf "\nArmada uses Grafana for monitoring, do the following in order to access it:" -printf "\n\t* type %bkubectl port-forward svc/kube-prometheus-stack-grafana 8081:80%b in your terminal" "$bs" "$be" -printf "\n\t* open %bhttp://localhost:8081%b in your browser" "$bs" "$be" -printf "\n\t* use %badmin:prom-operator%b as default admin credentials for login" "$bs" "$be" -printf "\n\t* open the %bArmada - Overview%b dashboard\n" "$bs" "$be" - -./docs/local/armadactl.sh diff --git a/docs/quickstart/grafana-armada-dashboard.json b/docs/quickstart/grafana-armada-dashboard.json deleted file mode 100644 index e718a825c04..00000000000 --- a/docs/quickstart/grafana-armada-dashboard.json +++ /dev/null @@ -1,1156 +0,0 @@ -{ - "dashboard": { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "id": null, - "iteration": 1572813374561, - "links": [], - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "fill": 6, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 8, - "x": 0, - "y": 0 - }, - "id": 5, - "interval": "1s", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "armada:queue:size", - "legendFormat": "{{ queueName }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Queued jobs", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "decimals": 3, - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 8, - "x": 8, - "y": 0 - }, - "id": 13, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "armada:queue:priority", - "legendFormat": "{{ queueName }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Queue priority", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": null, - "decimals": 10, - "fill": 7, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 8, - "x": 16, - "y": 0 - }, - "id": 44, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": true, - "pointradius": 2, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "(armada:queue:size > bool 1) * (100 / armada:queue:priority) / scalar(sum((armada:queue:size > bool 1) * (1 / armada:queue:priority)))", - "legendFormat": "{{ queueName }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "Queue share", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": null, - "format": "percent", - "label": null, - "logBase": 1, - "max": "100", - "min": null, - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 8 - }, - "id": 35, - "panels": [], - "title": "CPU", - "type": "row" - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 6, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 7, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": "cluster", - "repeatDirection": "h", - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-0", - "value": "cluster-0" - } - }, - "seriesOverrides": [ - { - "alias": "Available CPU", - "color": "#73BF69", - "fill": 0, - "linewidth": 2, - "stack": false - }, - { - "alias": "Used CPU", - "color": "#FADE2A", - "fill": 0, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "armada:monitoring:armada_pod_cpu_request:sum{phase=\"Running\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ label_armada_queue_id }}", - "refId": "A" - }, - { - "expr": " node:worker_node_allocatable_cpu_cores:sum", - "instant": false, - "legendFormat": "Available CPU", - "refId": "B" - }, - { - "expr": "container:worker_node_cpu_usage_seconds_total:sum", - "legendFormat": "Used CPU", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Running pods cpu request", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 6, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 9 - }, - "id": 45, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": null, - "repeatDirection": "h", - "repeatIteration": 1572813374561, - "repeatPanelId": 7, - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-1", - "value": "cluster-1" - } - }, - "seriesOverrides": [ - { - "alias": "Available CPU", - "color": "#73BF69", - "fill": 0, - "linewidth": 2, - "stack": false - }, - { - "alias": "Used CPU", - "color": "#FADE2A", - "fill": 0, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "armada:monitoring:armada_pod_cpu_request:sum{phase=\"Running\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ label_armada_queue_id }}", - "refId": "A" - }, - { - "expr": " node:worker_node_allocatable_cpu_cores:sum", - "instant": false, - "legendFormat": "Available CPU", - "refId": "B" - }, - { - "expr": "container:worker_node_cpu_usage_seconds_total:sum", - "legendFormat": "Used CPU", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Running pods cpu request", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "decimals": 0, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 17 - }, - "id": 29, - "panels": [], - "title": "Memory", - "type": "row" - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 5, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 18 - }, - "id": 17, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": "cluster", - "repeatDirection": "h", - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-0", - "value": "cluster-0" - } - }, - "seriesOverrides": [ - { - "alias": "Available Memory", - "color": "#73BF69", - "fill": 0, - "linewidth": 2, - "stack": false - }, - { - "alias": "Memory used", - "color": "#FADE2A", - "fill": 0, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "armada:monitoring:armada_pod_memory_request:sum{phase=\"Running\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ label_armada_queue_id }}", - "refId": "A" - }, - { - "expr": " node:worker_node_allocatable_memory_bytes:sum", - "instant": false, - "legendFormat": "Available Memory", - "refId": "B" - }, - { - "expr": "container:worker_node_memory_usage_bytes:sum", - "legendFormat": "Memory used", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Running pods memory request by queue", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "decbytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 5, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 46, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": null, - "repeatDirection": "h", - "repeatIteration": 1572813374561, - "repeatPanelId": 17, - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-1", - "value": "cluster-1" - } - }, - "seriesOverrides": [ - { - "alias": "Available Memory", - "color": "#73BF69", - "fill": 0, - "linewidth": 2, - "stack": false - }, - { - "alias": "Memory used", - "color": "#FADE2A", - "fill": 0, - "linewidth": 2, - "stack": false - } - ], - "spaceLength": 10, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "armada:monitoring:armada_pod_memory_request:sum{phase=\"Running\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ label_armada_queue_id }}", - "refId": "A" - }, - { - "expr": " node:worker_node_allocatable_memory_bytes:sum", - "instant": false, - "legendFormat": "Available Memory", - "refId": "B" - }, - { - "expr": "container:worker_node_memory_usage_bytes:sum", - "legendFormat": "Memory used", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Running pods memory request by queue", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "decbytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "collapsed": false, - "datasource": null, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 26 - }, - "id": 23, - "panels": [], - "title": "Pods", - "type": "row" - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 27 - }, - "id": 37, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": "cluster", - "repeatDirection": "h", - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-0", - "value": "cluster-0" - } - }, - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "namespace:pods_per_phase:sum{namespace=\"default\"} ", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ phase }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Pods by phase", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - }, - { - "aliasColors": { - "Failed": "semi-dark-red", - "Pending": "light-blue", - "Running": "light-green", - "Succeeded": "light-yellow", - "Unknown": "dark-purple" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "$cluster", - "decimals": null, - "description": "", - "fill": 0, - "fillGradient": 0, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 27 - }, - "id": 47, - "interval": "3s", - "legend": { - "avg": false, - "current": false, - "hideZero": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "maxPerRow": 6, - "nullPointMode": "null as zero", - "options": { - "dataLinks": [] - }, - "percentage": false, - "pointradius": 2, - "points": false, - "renderer": "flot", - "repeat": null, - "repeatDirection": "h", - "repeatIteration": 1572813374561, - "repeatPanelId": 37, - "scopedVars": { - "cluster": { - "selected": false, - "text": "cluster-1", - "value": "cluster-1" - } - }, - "seriesOverrides": [], - "spaceLength": 10, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "namespace:pods_per_phase:sum{namespace=\"default\"} ", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ phase }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeRegions": [], - "timeShift": null, - "title": "$cluster - Pods by phase", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "decimals": null, - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ], - "yaxis": { - "align": false, - "alignLevel": null - } - } - ], - "refresh": "5s", - "schemaVersion": 19, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "current": { - "tags": [], - "text": "All", - "value": [ - "$__all" - ] - }, - "hide": 0, - "includeAll": true, - "label": null, - "multi": true, - "name": "cluster", - "options": [], - "query": "prometheus", - "refresh": 1, - "regex": "cluster-.*", - "skipUrlSync": false, - "type": "datasource" - } - ] - }, - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ] - }, - "timezone": "", - "title": "Armada - Overview", - "uid": "jzf8f6cZz", - "version": 1 - } -} diff --git a/docs/quickstart/helm/values-executor-cluster-monitoring.yaml b/docs/quickstart/helm/values-executor-cluster-monitoring.yaml deleted file mode 100644 index f9bf6d654b4..00000000000 --- a/docs/quickstart/helm/values-executor-cluster-monitoring.yaml +++ /dev/null @@ -1,5 +0,0 @@ -additionalLabels: - app: prometheus-operator - release: prometheus-operator - -interval: 5s \ No newline at end of file diff --git a/docs/quickstart/helm/values-executor-prometheus.yaml b/docs/quickstart/helm/values-executor-prometheus.yaml deleted file mode 100644 index a8d4fbd5200..00000000000 --- a/docs/quickstart/helm/values-executor-prometheus.yaml +++ /dev/null @@ -1,22 +0,0 @@ -alertmanager: - enabled: false - -grafana: - enabled: false - -prometheus: - prometheusSpec: - serviceMonitorSelectorNilUsesHelmValues: false - ruleSelectorNilUsesHelmValues: false - service: - type: NodePort - nodePort: 30001 - -prometheusOperator: - admissionWebhooks: - enabled: false - tls: - enabled: false - tlsProxy: - enabled: false - createCustomResource: false diff --git a/docs/quickstart/helm/values-executor.yaml b/docs/quickstart/helm/values-executor.yaml deleted file mode 100644 index ca5e67b297e..00000000000 --- a/docs/quickstart/helm/values-executor.yaml +++ /dev/null @@ -1,11 +0,0 @@ -applicationConfig: - apiConnection: - ## Please note that this setting is insecure - ## Do not use this setting in a production environment - ## This should only be used for the quickstart and local testing - forceNoTls: true - kubernetes: - minimumPodAge: 0s - -prometheus: - enabled: true diff --git a/docs/quickstart/helm/values-pulsar.yaml b/docs/quickstart/helm/values-pulsar.yaml deleted file mode 100644 index a2aabc2e6a2..00000000000 --- a/docs/quickstart/helm/values-pulsar.yaml +++ /dev/null @@ -1,54 +0,0 @@ -## deployed with emptyDir -volumes: - persistence: false - -# disabled AntiAffinity -affinity: - anti_affinity: false - -# disable auto recovery -components: - autorecovery: false - -zookeeper: - replicaCount: 1 - -bookkeeper: - replicaCount: 1 - service: - spec: - publishNotReadyAddresses: true - -broker: - replicaCount: 1 - configData: - ## Enable `autoSkipNonRecoverableData` since bookkeeper is running - ## without persistence - autoSkipNonRecoverableData: "true" - # storage settings - managedLedgerDefaultEnsembleSize: "1" - managedLedgerDefaultWriteQuorum: "1" - managedLedgerDefaultAckQuorum: "1" - -proxy: - replicaCount: 1 - -grafana: - ingress: - enabled: true - resources: - requests: - memory: 512Mi - -images: - grafana: - # repository: apachepulsar/pulsar-grafana - #tag: 2.9.2 - #pullPolicy: IfNotPresent - repository: streamnative/apache-pulsar-grafana-dashboard-k8s - tag: 0.0.15 - pullPolicy: IfNotPresent - -extraInitCommand: > - until bin/pulsar-admin --admin-url http://pulsar-broker.default.svc.cluster.local:8080/ tenants list; do echo Waiting for broker... && sleep 1; done; - (bin/pulsar-admin --admin-url http://pulsar-broker.default.svc.cluster.local:8080/ tenants create armada && bin/pulsar-admin --admin-url http://pulsar-broker.default.svc.cluster.local:8080/ namespaces create armada/armada && bin/pulsar-admin --admin-url http://pulsar-broker.default.svc.cluster.local:8080/ topics create-partitioned-topic persistent://armada/armada/events -p 2) || true; diff --git a/docs/quickstart/helm/values-redis.yaml b/docs/quickstart/helm/values-redis.yaml deleted file mode 100644 index 3f34c86fbe4..00000000000 --- a/docs/quickstart/helm/values-redis.yaml +++ /dev/null @@ -1,3 +0,0 @@ -hardAntiAffinity: false -persistentVolume: - enabled: false diff --git a/docs/quickstart/helm/values-server-prometheus.yaml b/docs/quickstart/helm/values-server-prometheus.yaml deleted file mode 100644 index 4f774390cee..00000000000 --- a/docs/quickstart/helm/values-server-prometheus.yaml +++ /dev/null @@ -1,20 +0,0 @@ -alertmanager: - enabled: false - -prometheus: - prometheusSpec: - serviceMonitorSelectorNilUsesHelmValues: false - ruleSelectorNilUsesHelmValues: false -grafana: - service: - type: NodePort - nodePort: 30001 - -prometheusOperator: - admissionWebhooks: - enabled: false - tls: - enabled: false - tlsProxy: - enabled: false - createCustomResource: false diff --git a/docs/quickstart/helm/values-server.yaml b/docs/quickstart/helm/values-server.yaml deleted file mode 100644 index 5d2df06e302..00000000000 --- a/docs/quickstart/helm/values-server.yaml +++ /dev/null @@ -1,40 +0,0 @@ -ingressClass: "nginx" -clusterIssuer: "dummy-value" -hostnames: - - "dummy-value" -replicas: 3 - -applicationConfig: - pulsar: - url: "pulsar://pulsar-broker.default.svc.cluster.local:6650" - redis: - masterName: "mymaster" - addrs: - - "redis-redis-ha-announce-0.default.svc.cluster.local:26379" - - "redis-redis-ha-announce-1.default.svc.cluster.local:26379" - - "redis-redis-ha-announce-2.default.svc.cluster.local:26379" - poolSize: 1000 - eventsRedis: - masterName: "mymaster" - addrs: - - "redis-redis-ha-announce-0.default.svc.cluster.local:26379" - - "redis-redis-ha-announce-1.default.svc.cluster.local:26379" - - "redis-redis-ha-announce-2.default.svc.cluster.local:26379" - poolSize: 1000 - auth: - basicAuth: - enableAuthentication: false - anonymousAuth: true - permissionGroupMapping: - submit_any_jobs: ["everyone"] - create_queue: ["everyone"] - delete_queue: ["everyone"] - cancel_any_jobs: ["everyone"] - reprioritize_any_jobs: ["everyone"] - watch_all_events: ["everyone"] - execute_jobs: ["everyone"] - -prometheus: - enabled: true - -nodePort: 30000 diff --git a/docs/quickstart/img/grafana-screenshot.png b/docs/quickstart/img/grafana-screenshot.png deleted file mode 100644 index 5e2a1beb5039fc246c42ae3f372a9266b42f5343..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117093 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 diff --git a/docs/quickstart/index.md b/docs/quickstart/index.md deleted file mode 100644 index 1b77479b092..00000000000 --- a/docs/quickstart/index.md +++ /dev/null @@ -1,129 +0,0 @@ -# Armada Quickstart - -The main purpose of this guide is to install a minimal local Armada deployment for testing and evaluation purposes. - -## Pre-requisites - -- Git -- Docker (Docker Desktop recommended for local development on Windows/OSX) -- Helm v3.5+ -- Kind v0.11.1+ -- Kubectl - -## Installation -This guide will install Armada on 3 local Kubernetes clusters; one server and two executor clusters. - -Clone [this](https://github.com/armadaproject/armada) repository: - -```bash -git clone https://github.com/armadaproject/armada.git -cd armada -``` - -All commands are intended to be run from the root of the repository. - -Armada is a resource intensive application due to the need to run multiple Kubernetes clusters - for a local installation you will need at least 4 CPU cores and 16GB of RAM available. - -### One-click Setup - -To install Armada and all its dependencies you can use this script: - -``` -docs/local/setup.sh -``` - -Once completed, wait for all pods to be running via `kubectl get pod` - -Likewise you can remove the Armada components from your system: - -``` -docs/local/destroy.sh -``` - -## Usage -Create queues, submit some jobs and monitor progress: - -### Queue Creation -```bash -./armadactl create queue queue-a --priority-factor 1 -./armadactl create queue queue-b --priority-factor 2 -``` -For queues created in this way, user and group owners of the queue have permissions to: -- submit jobs -- cancel jobs -- reprioritize jobs -- watch queue - -For more control, queues can be created via `armadactl create`, which allows for setting specific permission; see the following example. - -```bash -./armadactl create -f ./docs/quickstart/queue-a.yaml -./armadactl create -f ./docs/quickstart/queue-b.yaml -``` - - -### Job Submission -``` -./armadactl submit ./docs/quickstart/job-queue-a.yaml -./armadactl submit ./docs/quickstart/job-queue-b.yaml -``` - -Watch individual queues: - -```bash -./armadactl watch queue-a job-set-1 -``` -```bash -./armadactl watch queue-b job-set-1 -``` - -Log in to the Grafana dashboard at [http://localhost:30001](http://localhost:30001) using the default credentials of `admin` / `prom-operator`. -Navigate to the Armada Overview dashboard to get a view of jobs progressing through the system. - -Try submitting lots of jobs and see queues get built and processed: - -```bash -for i in {1..50} -do - ./armadactl submit ./docs/quickstart/job-queue-a.yaml - ./armadactl submit ./docs/quickstart/job-queue-b.yaml -done -``` - -## Example output: - -CLI: - -```bash -$ ./armadactl watch queue-a job-set-1 -Watching job set job-set-1 -Nov 4 11:43:36 | Queued: 0, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobSubmittedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:36 | Queued: 1, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobQueuedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:36 | Queued: 1, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobSubmittedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:36 | Queued: 2, Leased: 0, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobQueuedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:38 | Queued: 1, Leased: 1, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobLeasedEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:38 | Queued: 0, Leased: 2, Pending: 0, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobLeasedEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:38 | Queued: 0, Leased: 1, Pending: 1, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobPendingEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:43:38 | Queued: 0, Leased: 0, Pending: 2, Running: 0, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobPendingEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:41 | Queued: 0, Leased: 0, Pending: 1, Running: 1, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobRunningEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:43:41 | Queued: 0, Leased: 0, Pending: 0, Running: 2, Succeeded: 0, Failed: 0, Cancelled: 0 | event: *api.JobRunningEvent, job id: 01drv3mey2mzmayf50631tzp9m -Nov 4 11:44:17 | Queued: 0, Leased: 0, Pending: 0, Running: 1, Succeeded: 1, Failed: 0, Cancelled: 0 | event: *api.JobSucceededEvent, job id: 01drv3mf7b6fd1rraeq1f554fn -Nov 4 11:44:26 | Queued: 0, Leased: 0, Pending: 0, Running: 0, Succeeded: 2, Failed: 0, Cancelled: 0 | event: *api.JobSucceededEvent, job id: 01drv3mey2mzmayf50631tzp9m -``` - - -### Grafana Configuration - -Run the following commands to setup Grafana in your environment: - -```bash -curl -X POST -i http://admin:prom-operator@localhost:30001/api/datasources -H "Content-Type: application/json" -d '{"name":"cluster-0","type":"prometheus","url":"http://'$EXECUTOR_0_IP':30001","access":"proxy","basicAuth":false}' -curl -X POST -i http://admin:prom-operator@localhost:30001/api/datasources -H "Content-Type: application/json" -d '{"name":"cluster-1","type":"prometheus","url":"http://'$EXECUTOR_1_IP':30001","access":"proxy","basicAuth":false}' -curl -X POST -i http://admin:prom-operator@localhost:30001/api/dashboards/import --data-binary @./docs/quickstart/grafana-armada-dashboard.json -H "Content-Type: application/json" -``` - -Grafana: - -![Armada Grafana dashboard](./img/grafana-screenshot.png "Armada Grafana dashboard") - -Note that the jobs in this demo simply run the `sleep` command so do not consume many resources. diff --git a/docs/quickstart/job-queue-a-preemptive.yaml b/docs/quickstart/job-queue-a-preemptive.yaml deleted file mode 100644 index 137ce0f5bca..00000000000 --- a/docs/quickstart/job-queue-a-preemptive.yaml +++ /dev/null @@ -1,23 +0,0 @@ -queue: queue-a -jobSetId: job-set-1 -jobs: - - priority: 1 - podSpec: - priorityClassName: armada-example-priority-class - terminationGracePeriodSeconds: 0 - restartPolicy: Never - containers: - - name: sleeper - image: alpine:latest - command: - - sh - args: - - -c - - sleep $(( (RANDOM % 60) + 30 )) - resources: - limits: - memory: 100Mi - cpu: 100m - requests: - memory: 100Mi - cpu: 100m diff --git a/docs/quickstart/job-queue-b.yaml b/docs/quickstart/job-queue-b.yaml deleted file mode 100644 index a6de6e50d7c..00000000000 --- a/docs/quickstart/job-queue-b.yaml +++ /dev/null @@ -1,23 +0,0 @@ -queue: queue-b -jobSetId: job-set-1 -jobs: - - namespace: default - priority: 0 - podSpec: - terminationGracePeriodSeconds: 0 - restartPolicy: Never - containers: - - name: sleeper - image: alpine:latest - command: - - sh - args: - - -c - - sleep $(( (RANDOM % 60) + 10 )) - resources: - limits: - memory: 128Mi - cpu: 0.2 - requests: - memory: 128Mi - cpu: 0.2 diff --git a/docs/quickstart/kind/kind-config-executor.yaml b/docs/quickstart/kind/kind-config-executor.yaml deleted file mode 100644 index 1ae052c93c5..00000000000 --- a/docs/quickstart/kind/kind-config-executor.yaml +++ /dev/null @@ -1,7 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - image: "kindest/node:v1.21.10" - - role: worker - image: "kindest/node:v1.21.10" diff --git a/docs/quickstart/kind/kind-config-server.yaml b/docs/quickstart/kind/kind-config-server.yaml deleted file mode 100644 index 0456354e678..00000000000 --- a/docs/quickstart/kind/kind-config-server.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - image: "kindest/node:v1.21.10" - - role: worker - image: "kindest/node:v1.21.10" - extraPortMappings: - - containerPort: 30000 - hostPort: 50051 - - containerPort: 30001 - hostPort: 30001 diff --git a/docs/quickstart/priority-class-example.yaml b/docs/quickstart/priority-class-example.yaml deleted file mode 100644 index 2faf77ae307..00000000000 --- a/docs/quickstart/priority-class-example.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: scheduling.k8s.io/v1 -kind: PriorityClass -metadata: - name: armada-example-priority-class -value: 10 -preemptionPolicy: PreemptLowerPriority -globalDefault: false -description: "Example priority class for preemptive Armada jobs." diff --git a/docs/quickstart/queue-a.yaml b/docs/quickstart/queue-a.yaml deleted file mode 100644 index 8c45005c492..00000000000 --- a/docs/quickstart/queue-a.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: armadaproject.io/v1beta1 -kind: Queue -name: queue-a -permissions: -- subjects: - - name: group2 - kind: Group - verbs: - - cancel - - reprioritize - - watch -priorityFactor: 3.0 -resourceLimits: - cpu: 1.0 - memory: 1.0 \ No newline at end of file diff --git a/docs/quickstart/queue-b.yaml b/docs/quickstart/queue-b.yaml deleted file mode 100644 index c405d9f6596..00000000000 --- a/docs/quickstart/queue-b.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: armadaproject.io/v1beta1 -kind: Queue -name: queue-b -permissions: -- subjects: - - name: group1 - kind: Group - - name: user1 - kind: User - verbs: - - submit - - cancel - - reprioritize - - watch -- subjects: - - name: group2 - kind: Group - verbs: - - cancel - - reprioritize - - watch -priorityFactor: 1.0 -resourceLimits: - cpu: 0.2 - memory: 0.1 \ No newline at end of file diff --git a/docs/quickstart/job-queue-a.yaml b/example/example-job.yaml similarity index 100% rename from docs/quickstart/job-queue-a.yaml rename to example/example-job.yaml diff --git a/example/kind-config.yaml b/example/kind-config.yaml deleted file mode 100644 index cebee6d5b98..00000000000 --- a/example/kind-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -kind: Cluster -apiVersion: kind.x-k8s.io/v1alpha4 -nodes: - - role: control-plane - - role: worker diff --git a/magefiles/ci.go b/magefiles/ci.go index 93369741ffa..6a911e231ed 100644 --- a/magefiles/ci.go +++ b/magefiles/ci.go @@ -94,7 +94,7 @@ func findOrDownloadArmadaCtl() string { return path } - err = sh.Run("sh", "./docs/local/armadactl.sh") + err = sh.Run("sh", "./scripts/get-armadactl.sh") if err != nil { return "" } diff --git a/plugins/armadactl.yml b/plugins/armadactl.yml index 61dc90492a3..6e1cbfd85f4 100644 --- a/plugins/armadactl.yml +++ b/plugins/armadactl.yml @@ -5,12 +5,12 @@ metadata: spec: version: v0.3.88 homepage: https://github.com/armadaproject/armada - shortDescription: Command line utility to submit many jobs to armada + shortDescription: Command line utility used for interacting with Armada API description: | armadactl is a command-line tool used for managing jobs in the Armada workload orchestration system. It provides functionality for creating, updating, and deleting jobs, as well as monitoring job status and resource usage. caveats: | - Before using the Armada CLI, make sure you have working armada enviornment + Before using the Armada CLI, make sure you have working armada environment or a armadactl.yaml file that points to a valid armada cluster. platforms: - selector: @@ -33,4 +33,4 @@ spec: arch: amd64 uri: https://github.com/armadaproject/armada/releases/download/v0.3.8655/armadactl_0.3.8655_windows_amd64.zip sha256: 27774e39b8a29603671c21ed9487fbd073eb408535afe5de5f336e84dc13998b - bin: armadactl.exe \ No newline at end of file + bin: armadactl.exe diff --git a/scripts/get-armadactl.sh b/scripts/get-armadactl.sh new file mode 100755 index 00000000000..52a881f79ff --- /dev/null +++ b/scripts/get-armadactl.sh @@ -0,0 +1,61 @@ +#!/bin/sh -e + +# Determine Platform +SYSTEM=$(uname | sed 's/MINGW.*/windows/' | tr A-Z a-z) +if [ "$SYSTEM" = "windows" ]; then + ARCHIVE_TYPE=zip + UNARCHIVE="zcat > armadactl.exe" +else + ARCHIVE_TYPE=tar.gz + UNARCHIVE="tar xzf -" +fi + +# Determine architecture +get_arch() { + case $(uname -m) in + "x86_64" | "amd64" ) echo "amd64" ;; + "i386" | "i486" | "i586") echo "386" ;; + "aarch64" | "arm64" | "arm") echo "arm64" ;; + "mips64el") echo "mips64el" ;; + "mips64") echo "mips64" ;; + "mips") echo "mips" ;; + *) echo "unknown" ;; + esac +} + +ARCH=$(get_arch) +if [ "$SYSTEM" = "darwin" ]; then + ARCH="all" +fi + +# Get latest release +get_latest_release() { + curl --silent "https://api.github.com/repos/armadaproject/armada/releases/latest" | \ + grep '"tag_name":' | \ + sed -E 's/.*"([^"]+)".*/\1/' +} + +VERSION=$(get_latest_release) + +ARMADACTL_URL="https://github.com/armadaproject/armada/releases/download/$VERSION/armadactl_${VERSION#v}_${SYSTEM}_${ARCH}.${ARCHIVE_TYPE}" + +echo "Downloading armadactl $VERSION for $SYSTEM/$ARCH" + +# Download and untar/unzip armadactl +if curl -sL $ARMADACTL_URL | sh -c "$UNARCHIVE" ; then + echo "armadactl downloaded successfully" + + # Move armadactl binary to a directory in user's PATH + TARGET_DIR="$HOME/bin" # Change this to the desired target directory in your user's home + mkdir -p "$TARGET_DIR" + cp armadactl "$TARGET_DIR/" + export PATH="$TARGET_DIR:$PATH" + echo "armadactl copied to $TARGET_DIR/armadactl" + echo "armadactl is now available on your PATH" + +else + echo "Something is amiss!" + echo "Please visit:" + echo " - https://github.com/armadaproject/armada/releases/latest" + echo "to find the latest armadactl binary for your platform" +fi