From e0d7bb5de78e0347aac0ac33862955629c67bfa9 Mon Sep 17 00:00:00 2001 From: Steve Date: Mon, 16 Dec 2019 16:13:25 +1000 Subject: [PATCH 1/3] Bay release 1.1.0 (#42) * SDPA-3169 Adds new branding (#36) * SDPA-3169 Adds new branding * SDPA-3169 Updated readme.md * [SDPA-3447] : Adding a check in the Bay Drupal settings.php file to allow for the inclusion of branch specific settings. (#39) * [SDPA-3447] : Adding a check in the Bay Drupal settings.php file to allow for the inclusion of branch specific settings. * [SDPA-3447] : Removing ClamAV fromthe php and cli Images. * [SDPA-3447] : Removing the specific version update for curl. * Switching from update-cache to no-cache in apk to reduce image size. * Rationalise the bay images with the Amazee images. (#37) * Remove custom CURL dependency. @see https://github.com/amazeeio/lagoon/issues/1111 * Updating nginx container. - Removes custom Drupal conf. * Remove custom mysql conf. * Remove my.cnf * Remove Lagoon files. * Trigger CI. * Trigger CI * Trigger CI * Update PHP to 7.2. (#40) * [SDPSUP-987] : Set hotlink to true in settings.php (#41) --- .dockerignore | 7 - .env.defaults | 7 - .eslintignore | 2 - .flowconfig | 22 - .gitignore | 21 - .lagoon.keycloak-secrets.yaml | 45 - .lagoon.logs-db-secrets.yaml | 45 - .lagoon.secrets.yaml | 81 - .lagoon.yml | 60 - .prettierignore | 2 - .prettierrc | 3 - Jenkinsfile | 134 - Jenkinsfile.end2end | 21 - LICENSE | 201 - Makefile | 812 - README.md | 41 +- bay/images/Dockerfile.builder | 10 +- bay/images/Dockerfile.circle | 2 +- bay/images/Dockerfile.mariadb | 6 - bay/images/Dockerfile.nginx | 2 - bay/images/Dockerfile.php | 10 +- bay/images/docker/drupal.conf | 144 - bay/images/docker/my.cnf | 43 - bay/images/docker/server.cnf | 33 +- bay/images/docker/settings.php | 13 + build/.gitkeep | 0 charts-values/clair/values.yaml | 0 charts-values/grafana/values.yaml | 19024 ---------------- charts-values/prometheus/values.yaml | 19 - charts/clair/.helmignore | 21 - charts/clair/Chart.yaml | 11 - charts/clair/requirements.yaml | 5 - charts/clair/templates/_helpers.tpl | 23 - charts/clair/templates/configmap.yaml | 92 - charts/clair/templates/deployment.yaml | 47 - charts/clair/templates/ingress.yaml | 32 - charts/clair/templates/service.yaml | 21 - charts/clair/values.yaml | 71 - charts/grafana-dpc/Chart.yaml | 11 - charts/grafana-dpc/README.md | 51 - charts/grafana-dpc/templates/NOTES.txt | 38 - charts/grafana-dpc/templates/_helpers.tpl | 24 - charts/grafana-dpc/templates/configmap.yaml | 15 - .../templates/dashboards-configmap.yaml | 12 - charts/grafana-dpc/templates/deployment.yaml | 118 - charts/grafana-dpc/templates/ingress.yaml | 32 - charts/grafana-dpc/templates/job-notify.yaml | 49 - charts/grafana-dpc/templates/job.yaml | 53 - charts/grafana-dpc/templates/pvc.yaml | 33 - charts/grafana-dpc/templates/route.yaml | 25 - .../grafana-dpc/templates/secret-oauth.yaml | 15 - charts/grafana-dpc/templates/secret.yaml | 17 - charts/grafana-dpc/templates/svc.yaml | 40 - charts/grafana-dpc/values.yaml | 421 - charts/prometheus-dpc/.helmignore | 21 - charts/prometheus-dpc/Chart.yaml | 14 - charts/prometheus-dpc/README.md | 248 - charts/prometheus-dpc/templates/NOTES.txt | 100 - charts/prometheus-dpc/templates/_helpers.tpl | 72 - .../alertmanager-clusterrolebinding.yaml | 20 - .../templates/alertmanager-configmap.yaml | 14 - .../templates/alertmanager-deployment.yaml | 93 - .../templates/alertmanager-ingress.yaml | 33 - .../templates/alertmanager-networkpolicy.yaml | 26 - .../templates/alertmanager-pvc.yaml | 31 - .../templates/alertmanager-service.yaml | 49 - .../alertmanager-serviceaccount.yaml | 12 - .../kube-state-metrics-clusterrole.yaml | 53 - ...kube-state-metrics-clusterrolebinding.yaml | 20 - .../kube-state-metrics-deployment.yaml | 43 - .../kube-state-metrics-networkpolicy.yaml | 26 - .../kube-state-metrics-serviceaccount.yaml | 12 - .../templates/kube-state-metrics-svc.yaml | 46 - .../node-exporter-clusterrolebinding.yaml | 20 - .../templates/node-exporter-daemonset.yaml | 79 - .../templates/node-exporter-service.yaml | 46 - .../node-exporter-serviceaccount.yaml | 12 - .../templates/openshift-scc.yaml | 43 - .../templates/pushgateway-deployment.yaml | 51 - .../templates/pushgateway-ingress.yaml | 33 - .../templates/pushgateway-service.yaml | 46 - .../templates/server-clusterrole.yaml | 35 - .../templates/server-clusterrolebinding.yaml | 20 - .../templates/server-configmap.yaml | 14 - .../templates/server-deployment.yaml | 109 - .../templates/server-gluster-pvc.yaml | 13 - .../templates/server-ingress.yaml | 33 - .../templates/server-networkpolicy.yaml | 21 - .../prometheus-dpc/templates/server-pvc.yaml | 31 - .../templates/server-route.yaml | 25 - .../templates/server-service.yaml | 47 - .../templates/server-serviceaccount.yaml | 12 - charts/prometheus-dpc/values.yaml | 813 - charts/trigger-quay-builds/.helmignore | 21 - charts/trigger-quay-builds/Chart.yaml | 4 - .../templates/_helpers.tpl | 16 - .../templates/cronjob.yaml | 27 - .../trigger-quay-builds/templates/secret.yaml | 6 - charts/trigger-quay-builds/values.yaml | 11 - cli/.babelrc.js | 29 - cli/.eslintignore | 2 - cli/.eslintrc.js | 1 - cli/.gitignore | 6 - cli/.projectile | 0 cli/.yarnrc | 1 - cli/10-ssh-agent.sh | 8 - cli/Dockerfile | 33 - cli/README.md | 142 - cli/bin/lagu.js | 10 - cli/jest.config.js | 7 - cli/package.json | 85 - cli/scripts/execute.js | 3 - .../__tests__/__snapshots__/e2e.test.js.snap | 145 - cli/src/__tests__/e2e.test.js | 238 - cli/src/__tests__/fixtures/.gitignore | 1 - cli/src/__tests__/fixtures/.gitkeep | 0 cli/src/cli/answerWithOption.js | 75 - cli/src/cli/promptUntilValidKeyPath.js | 30 - cli/src/cli/registerCommands.js | 26 - cli/src/cli/setConfigForHandlers.js | 70 - .../__snapshots__/customer.test.js.snap | 35 - .../__tests__/__snapshots__/init.test.js.snap | 58 - .../__snapshots__/project.test.js.snap | 36 - .../__snapshots__/projects.test.js.snap | 89 - cli/src/commands/__tests__/customer.test.js | 104 - cli/src/commands/__tests__/init.test.js | 96 - cli/src/commands/__tests__/project.test.js | 108 - cli/src/commands/__tests__/projects.test.js | 238 - cli/src/commands/customer.js | 114 - cli/src/commands/environments.js | 112 - cli/src/commands/init.js | 252 - cli/src/commands/login.js | 67 - cli/src/commands/logout.js | 34 - cli/src/commands/project.js | 147 - .../__snapshots__/project-create.test.js.snap | 101 - .../__tests__/project-create.test.js | 294 - cli/src/commands/projectCommands/create.js | 465 - cli/src/commands/projectCommands/delete.js | 114 - cli/src/commands/projects.js | 83 - cli/src/config/getApiConfig.js | 68 - cli/src/config/getSshConfig.js | 50 - cli/src/config/globalOptions.js | 37 - cli/src/config/index.js | 53 - .../writeConfigFile.test.js.snap | 12 - cli/src/configFile/__tests__/lagoon.yml | 1 - .../__tests__/parseConfigFile.test.js | 23 - .../__tests__/writeConfigFile.test.js | 49 - cli/src/configFile/parseConfigFile.js | 15 - cli/src/configFile/readConfigFile.js | 21 - cli/src/configFile/writeConfigFile.js | 53 - .../__tests__/__snapshots__/csv.test.js.snap | 19 - .../__tests__/__snapshots__/json.test.js.snap | 40 - .../__snapshots__/simple.test.js.snap | 16 - .../__snapshots__/table.test.js.snap | 14 - cli/src/formatters/__tests__/csv.test.js | 27 - cli/src/formatters/__tests__/json.test.js | 27 - cli/src/formatters/__tests__/simple.test.js | 27 - cli/src/formatters/__tests__/table.test.js | 27 - cli/src/formatters/csv.js | 3 - cli/src/formatters/json.js | 3 - cli/src/formatters/simple.js | 20 - cli/src/formatters/table.js | 56 - cli/src/index.js | 3 - cli/src/types/Command.js | 18 - cli/src/types/Config.js | 10 - cli/src/types/ConfigFile.js | 32 - cli/src/types/Format.js | 3 - .../__snapshots__/format.test.js.snap | 69 - .../__snapshots__/printErrors.test.js.snap | 61 - .../__snapshots__/runSshCommand.test.js.snap | 23 - cli/src/util/__tests__/format.test.js | 93 - cli/src/util/__tests__/printErrors.test.js | 66 - cli/src/util/__tests__/queryGraphQL.test.js | 130 - cli/src/util/__tests__/request.test.js | 81 - cli/src/util/__tests__/runSshCommand.test.js | 50 - cli/src/util/format.js | 34 - cli/src/util/fs.js | 36 - cli/src/util/getCommandOptions.js | 20 - cli/src/util/gql.js | 20 - cli/src/util/printErrors.js | 64 - cli/src/util/queryGraphQL.js | 85 - cli/src/util/request.js | 51 - cli/src/util/runSshCommand.js | 43 - dashboards/examples/deployment-dashboard.json | 668 - dashboards/examples/ingress.json | 685 - ...ubernetes-capacity-planning-dashboard.json | 921 - .../kubernetes-cluster-health-dashboard.json | 634 - .../kubernetes-cluster-monitoring.json | 2079 -- .../kubernetes-cluster-status-dashboard.json | 731 - ...rnetes-control-plane-status-dashboard.json | 583 - ...ubernetes-resource-requests-dashboard.json | 380 - dashboards/examples/nodes-dashboard.json | 777 - dashboards/examples/nodes.json | 872 - dashboards/examples/pod_metrics.json | 920 - dashboards/examples/pods-dashboard.json | 373 - .../examples/resource-cpu-requests.json | 353 - .../examples/resource-memory-requests.json | 353 - dashboards/examples/resource-requests.json | 452 - .../examples/statefulset-dashboard.json | 647 - dashboards/examples/system.json | 1948 -- dashboards/in-use/alerts.json | 256 - .../in-use/kubernetes-capacity-planning.json | 1078 - .../kubernetes-control-plane-status.json | 320 - dashboards/in-use/kubernetes-deployments.json | 822 - dashboards/in-use/kubernetes-pods.json | 1623 -- .../in-use/kubernetes-resource-requests.json | 466 - .../in-use/kubernetes-statefulsets.json | 802 - .../in-use/mysql-cross-server-graphs.json | 926 - dashboards/in-use/mysql-disk-performance.json | 1000 - dashboards/in-use/mysql-galera-graphs.json | 1150 - dashboards/in-use/mysql-innodb-metrics.json | 2164 -- dashboards/in-use/mysql-myisam-metrics.json | 588 - dashboards/in-use/mysql-overview.json | 2742 --- dashboards/in-use/mysql-summary.json | 1089 - dashboards/in-use/mysql-trends.json | 900 - dashboards/in-use/nodes.json | 911 - dashboards/in-use/system.json | 1953 -- .../temp/Alerts Copy-1516600505131.json | 782 - .../temp/Cluster - Pods-1516597155979.json | 303 - docker-compose.end2end.yaml | 19 - docker-compose.yaml | 393 - docs/SUMMARY.md | 17 - docs/administering_lagoon/create-project.gql | 77 - docs/administering_lagoon/graphql_api.md | 405 - docs/administering_lagoon/install.md | 67 - .../openshift_requirements.md | 30 - docs/clair.md | 5 - docs/code_of_conduct.md | 46 - docs/developing_lagoon/contributing.md | 25 - docs/developing_lagoon/index.md | 89 - docs/developing_lagoon/tests.md | 54 - docs/helm.md | 63 - docs/images/SDP_Bay_product_logo_JPG.JPG | Bin 0 -> 82909 bytes docs/images/SDP_Logo_VicGov_RGB.jpg | Bin 0 -> 381014 bytes docs/images/Salsa.png | Bin 0 -> 27430 bytes docs/images/bb_webhook_1.png | Bin 35575 -> 0 bytes .../first_deployment_slack_2nd_success.jpg | Bin 17187 -> 0 bytes docs/images/first_deployment_slack_start.jpg | Bin 5853 -> 0 bytes .../images/first_deployment_slack_success.jpg | Bin 12104 -> 0 bytes docs/images/gh_webhook_1.png | Bin 15719 -> 0 bytes docs/images/gh_webhook_2.png | Bin 57108 -> 0 bytes docs/images/gl_webhook_1.png | Bin 48384 -> 0 bytes docs/images/grafana.png | Bin 66503 -> 0 bytes docs/images/lagoon-ui-production.png | Bin 11389 -> 0 bytes docs/images/pod_search_domains.jpg | Bin 181907 -> 0 bytes docs/images/prometheus-kube-state-metrics.png | Bin 32760 -> 0 bytes docs/images/prometheus-node-exporter.png | Bin 29289 -> 0 bytes docs/images/prometheus-server.png | Bin 53782 -> 0 bytes docs/index.md | 43 - docs/links.md | 20 - docs/metrics_architecture.md | 56 - docs/metrics_charts.md | 74 - docs/metrics_dashboards.md | 260 - docs/metrics_install.md | 179 - docs/quay.md | 73 - docs/tests.md | 69 - docs/troubleshooting.md | 57 - docs/using_lagoon/backups.md | 19 - docs/using_lagoon/build_deploy_process.md | 100 - docs/using_lagoon/configure_webhooks.md | 44 - docs/using_lagoon/docker-compose_yml.md | 152 - docs/using_lagoon/docker_images/nginx.md | 48 - docs/using_lagoon/docker_images/php-fpm.md | 70 - .../drupal/drupal7-mariadb/.dockerignore | 1 - .../drupal/drupal7-mariadb/.lagoon.yml | 24 - .../drupal/drupal7-mariadb/Dockerfile.cli | 3 - .../drupal/drupal7-mariadb/Dockerfile.nginx | 7 - .../drupal/drupal7-mariadb/Dockerfile.php | 6 - .../drupal/drupal7-mariadb/docker-compose.yml | 120 - .../drupal7-mariadb/drush/aliases.drushrc.php | 19 - .../drupal/drupal7-mariadb/drush/drushrc.php | 15 - .../sites/default/all.settings.php | 15 - .../sites/default/development.settings.php | 32 - .../sites/default/production.settings.php | 32 - .../sites/default/settings.php | 97 - .../drupal8-composer-mariadb/.dockerignore | 3 - .../drupal8-composer-mariadb/.gitignore | 21 - .../drupal8-composer-mariadb/.lagoon.yml | 29 - .../drupal8-composer-mariadb/Dockerfile.cli | 11 - .../drupal8-composer-mariadb/Dockerfile.nginx | 9 - .../drupal8-composer-mariadb/Dockerfile.php | 6 - .../docker-compose.yml | 120 - .../drush/aliases.drushrc.php | 19 - .../drush/drushrc.php | 15 - .../web/sites/default/all.services.yml | 4 - .../web/sites/default/all.settings.php | 14 - .../sites/default/development.services.yml | 15 - .../sites/default/development.settings.php | 30 - .../sites/default/example.settings.local.php | 13 - .../web/sites/default/production.services.yml | 11 - .../web/sites/default/production.settings.php | 25 - .../web/sites/default/settings.php | 159 - .../drupal8-composer-postgres/.dockerignore | 3 - .../drupal8-composer-postgres/.gitignore | 21 - .../drupal8-composer-postgres/.lagoon.yml | 26 - .../drupal8-composer-postgres/Dockerfile.cli | 11 - .../Dockerfile.nginx | 9 - .../drupal8-composer-postgres/Dockerfile.php | 6 - .../docker-compose.yml | 120 - .../drush/aliases.drushrc.php | 19 - .../drush/drushrc.php | 15 - .../web/sites/default/all.services.yml | 4 - .../web/sites/default/all.settings.php | 16 - .../sites/default/development.services.yml | 15 - .../sites/default/development.settings.php | 30 - .../web/sites/default/production.services.yml | 11 - .../web/sites/default/production.settings.php | 25 - .../web/sites/default/settings.php | 118 - docs/using_lagoon/drupal/drush9.md | 47 - docs/using_lagoon/drupal/first_deployment.md | 124 - docs/using_lagoon/drupal/lagoonize.md | 139 - docs/using_lagoon/drupal/services/mariadb.md | 38 - docs/using_lagoon/drupal/services/redis.md | 101 - docs/using_lagoon/drupal/services/solr.md | 46 - docs/using_lagoon/drupal/services/varnish.md | 109 - docs/using_lagoon/environment_files.md | 24 - docs/using_lagoon/environment_types.md | 17 - docs/using_lagoon/first_deployment.md | 54 - docs/using_lagoon/golive.md | 92 - docs/using_lagoon/graphql_api.md | 83 - docs/using_lagoon/index.md | 62 - docs/using_lagoon/lagoon_yml.md | 255 - .../local_development_environments.md | 14 - docs/using_lagoon/logging.md | 37 - docs/using_lagoon/migrations/amazeeio.md | 59 - docs/using_lagoon/remote_shell.md | 63 - docs/using_lagoon/service_types.md | 29 - docs/using_lagoon/setup_project.md | 36 - docs/using_lagoon/workflows.md | 94 - flow-typed/custom/emit.js | 4 - flow-typed/custom/execa_v0.10.x.js | 104 - flow-typed/custom/express_v4.16.x.js | 315 - flow-typed/custom/mocha.js | 3 - flow-typed/custom/ramda_v0.x.x.js | 2112 -- flow-typed/custom/yargs_v10.x.x.js | 259 - flow-typed/npm/babel-cli_vx.x.x.js | 108 - flow-typed/npm/babel-core_vx.x.x.js | 227 - flow-typed/npm/babel-eslint_vx.x.x.js | 80 - flow-typed/npm/babel-jest_vx.x.x.js | 32 - ...el-plugin-syntax-async-functions_vx.x.x.js | 32 - ...lugin-transform-flow-strip-types_vx.x.x.js | 32 - ...gin-transform-object-rest-spread_vx.x.x.js | 32 - ...bel-plugin-transform-regenerator_vx.x.x.js | 32 - flow-typed/npm/babel-polyfill_vx.x.x.js | 67 - flow-typed/npm/babel-preset-es2015_vx.x.x.js | 32 - flow-typed/npm/body-parser_v1.x.x.js | 41 - flow-typed/npm/chalk_v1.x.x.js | 114 - flow-typed/npm/co_vx.x.x.js | 33 - .../npm/eslint-plugin-flow-vars_vx.x.x.js | 45 - .../npm/eslint-plugin-flowtype_vx.x.x.js | 291 - .../npm/eslint-plugin-graphql_vx.x.x.js | 32 - flow-typed/npm/eslint_vx.x.x.js | 2349 -- flow-typed/npm/flow-bin_v0.x.x.js | 6 - flow-typed/npm/inquirer_v1.x.x.js | 339 - flow-typed/npm/jest_v22.x.x.js | 661 - flow-typed/npm/js-yaml_vx.x.x.js | 255 - flow-typed/npm/jsonwebtoken_vx.x.x.js | 227 - flow-typed/npm/lint-staged_vx.x.x.js | 108 - flow-typed/npm/morgan_vx.x.x.js | 33 - flow-typed/npm/nano_vx.x.x.js | 564 - flow-typed/npm/node-fetch_vx.x.x.js | 80 - flow-typed/npm/nodemon_vx.x.x.js | 214 - flow-typed/npm/pre-commit_vx.x.x.js | 52 - flow-typed/npm/prettier_vx.x.x.js | 73 - flow-typed/npm/rimraf_vx.x.x.js | 39 - flow-typed/npm/ssh2_vx.x.x.js | 109 - flow-typed/npm/sshpk_vx.x.x.js | 186 - flow-typed/npm/table_vx.x.x.js | 389 - flow-typed/npm/winston_vx.x.x.js | 214 - helpers/annotate-pvc-backup.sh | 10 - helpers/k8up-initiate.sh | 95 - helpers/mariadb-galera2shared.sh | 114 - helpers/mariadb-single2shared-no-nginx.sh | 106 - helpers/mariadb-single2shared-wordpress.sh | 120 - helpers/mariadb-single2shared.sh | 120 - helpers/reclaim-pv.sh | 119 - helpers/run-in-all-lagoon-projects.sh | 12 - helpers/sharedmigrate.sh | 200 - images/athenapdf-service/Dockerfile | 30 - images/athenapdf-service/entrypoint.sh | 12 - images/commons/.bashrc | 38 - images/commons/Dockerfile | 40 - images/commons/docker-sleep | 2 - images/commons/fix-permissions | 6 - images/commons/lagoon/cronjob.sh | 14 - images/commons/lagoon/entrypoints.bash | 15 - images/commons/lagoon/entrypoints.sh | 15 - images/commons/lagoon/entrypoints/00-umask.sh | 4 - .../commons/lagoon/entrypoints/10-passwd.sh | 15 - .../commons/lagoon/entrypoints/50-dotenv.sh | 39 - .../lagoon/entrypoints/55-generate-env.sh | 4 - .../commons/lagoon/entrypoints/90-cronjobs.sh | 10 - images/curator/Dockerfile | 36 - images/docker-host/Dockerfile | 38 - images/docker-host/prune-images.sh | 7 - images/docker-host/update-push-images.sh | 26 - images/elasticsearch/Dockerfile | 54 - images/elasticsearch/configure-es.sh | 44 - images/elasticsearch/docker-entrypoint.sh | 16 - images/elasticsearch/peer-finder | Bin 2267197 -> 0 bytes images/kibana/Dockerfile | 42 - images/logstash/Dockerfile | 39 - images/mariadb-drupal/Dockerfile | 6 - images/mariadb-galera-drupal/Dockerfile | 6 - images/mariadb-galera/Dockerfile | 135 - .../entrypoints/100-fix-data-subpath.sh | 16 - .../entrypoints/100-mariadb-logging.bash | 24 - .../entrypoints/150-mariadb-performance.bash | 13 - .../entrypoints/200-mariadb-envplate.bash | 5 - .../entrypoints/201-maxscale-envplate.bash | 3 - .../entrypoints/9999-mariadb-galera-init.bash | 131 - images/mariadb-galera/maxscale-start.sh | 2 - images/mariadb-galera/maxscale.cnf | 60 - images/mariadb-galera/maxscale.sql | 12 - images/mariadb-galera/my.cnf | 43 - images/mariadb-galera/mysql-backup.sh | 109 - .../mariadb-galera/root/usr/bin/peer-finder | Bin 3169760 -> 0 bytes .../root/usr/include/bits/wordsize.h | 13 - .../mysql/configure-galera.sh | 52 - .../share/container-scripts/mysql/galera.cnf | 20 - .../mysql/readiness-probe.sh | 12 - images/mariadb/Dockerfile | 76 - .../entrypoints/100-mariadb-logging.bash | 24 - .../entrypoints/150-mariadb-performance.bash | 13 - .../entrypoints/200-mariadb-envplate.bash | 5 - .../entrypoints/9999-mariadb-init.bash | 114 - images/mariadb/my.cnf | 43 - images/mariadb/mysql-backup.sh | 109 - .../mysql/readiness-probe.sh | 12 - images/mongo/Dockerfile | 34 - images/nginx-drupal/Dockerfile | 11 - images/nginx-drupal/drupal.conf | 151 - images/nginx/Dockerfile | 54 - images/nginx/docker-entrypoint | 22 - images/nginx/fastcgi.conf | 62 - images/nginx/helpers/000_variables.conf | 2 - images/nginx/helpers/010_redirects.conf | 4 - images/nginx/helpers/020_basic-auth.conf | 3 - images/nginx/helpers/030_ipv6-xfwdfor.conf | 13 - .../100_x-robots-header-development.conf | 15 - images/nginx/nginx.conf | 120 - images/nginx/redirects-map.conf | 26 - images/nginx/static-files.conf | 12 - images/node/Dockerfile | 48 - images/node/builder/Dockerfile | 34 - images/oc-build-deploy-dind/Dockerfile | 24 - images/oc-build-deploy-dind/README.md | 52 - .../build-deploy-docker-compose.sh | 913 - images/oc-build-deploy-dind/build-deploy.sh | 66 - .../oc-build-deploy-dind/docker-entrypoint.sh | 28 - .../openshift-templates/backup/schedule.yml | 63 - .../cli-persistent/custom-cronjob.yml | 108 - .../cli-persistent/deployment.yml | 128 - .../openshift-templates/cli/deployment.yml | 109 - .../openshift-templates/configmap.yml | 55 - .../custom/custom-cronjob.yml | 85 - .../elasticsearch-cluster/services.yml | 80 - .../elasticsearch-cluster/statefulset.yml | 116 - .../elasticsearch/deployment.yml | 111 - .../openshift-templates/elasticsearch/pvc.yml | 53 - .../elasticsearch/services.yml | 53 - .../openshift-templates/kibana/deployment.yml | 96 - .../openshift-templates/kibana/routes.yml | 59 - .../openshift-templates/kibana/services.yml | 51 - .../logstash/deployment.yml | 96 - .../openshift-templates/logstash/services.yml | 53 - .../mariadb-galera/cronjobs.yml | 3 - .../mariadb-galera/deployment.yml | 101 - .../mariadb-galera/services.yml | 76 - .../mariadb-galera/statefulset.yml | 114 - .../mariadb-shared/servicebroker.yml | 2 - .../mariadb-single/cronjobs.yml | 3 - .../mariadb-single/deployment.yml | 110 - .../mariadb-single/pvc.yml | 52 - .../mariadb-single/services.yml | 53 - .../mongo-shared/servicebroker.yml | 2 - .../openshift-templates/mongo/deployment.yml | 100 - .../openshift-templates/mongo/pvc.yml | 47 - .../openshift-templates/mongo/services.yml | 53 - .../nginx-php-persistent/deployment.yml | 172 - .../nginx-php-persistent/pvc.yml | 59 - .../nginx-php-persistent/routes.yml | 59 - .../nginx-php-persistent/services.yml | 53 - .../nginx-php-redis-persistent/deployment.yml | 207 - .../nginx-php-redis-persistent/pvc.yml | 59 - .../nginx-php-redis-persistent/routes.yml | 59 - .../nginx-php-redis-persistent/services.yml | 70 - .../nginx-php/deployment.yml | 154 - .../openshift-templates/nginx-php/routes.yml | 59 - .../nginx-php/services.yml | 53 - .../openshift-templates/nginx/deployment.yml | 114 - .../openshift-templates/nginx/routes.yml | 59 - .../openshift-templates/nginx/services.yml | 53 - .../node-persistent/deployment.yml | 129 - .../node-persistent/pvc.yml | 59 - .../node-persistent/routes.yml | 59 - .../node-persistent/services.yml | 53 - .../openshift-templates/node/deployment.yml | 110 - .../openshift-templates/node/routes.yml | 59 - .../openshift-templates/node/services.yml | 53 - .../openshift-templates/postgres/cronjobs.yml | 3 - .../postgres/deployment.yml | 104 - .../openshift-templates/postgres/pvc.yml | 44 - .../openshift-templates/postgres/services.yml | 53 - .../rabbitmq-cluster/services.yml | 80 - .../rabbitmq-cluster/statefulset.yml | 131 - .../rabbitmq/deployment.yml | 103 - .../openshift-templates/rabbitmq/pvc.yml | 44 - .../openshift-templates/rabbitmq/services.yml | 57 - .../redis-persistent/deployment.yml | 116 - .../redis-persistent/pvc.yml | 59 - .../redis-persistent/services.yml | 62 - .../openshift-templates/redis/deployment.yml | 97 - .../openshift-templates/redis/services.yml | 53 - .../openshift-templates/route.yml | 63 - .../openshift-templates/solr/deployment.yml | 113 - .../openshift-templates/solr/pvc.yml | 52 - .../openshift-templates/solr/services.yml | 53 - .../varnish-persistent/deployment.yml | 116 - .../varnish-persistent/pvc.yml | 59 - .../varnish-persistent/routes.yml | 59 - .../varnish-persistent/services.yml | 57 - .../varnish/deployment.yml | 109 - .../openshift-templates/varnish/routes.yml | 59 - .../openshift-templates/varnish/services.yml | 57 - .../scripts/convert-crontab.sh | 100 - .../scripts/exec-additional-yaml.sh | 12 - .../scripts/exec-build.sh | 6 - .../scripts/exec-monitor-daemonset.sh | 66 - .../scripts/exec-monitor-deploy.sh | 53 - .../scripts/exec-monitor-statefulset.sh | 66 - .../scripts/exec-openshift-create-pvc.sh | 6 - .../scripts/exec-openshift-create-route.sh | 22 - .../exec-openshift-create-servicebroker.sh | 25 - .../exec-openshift-resources-with-images.sh | 46 - .../scripts/exec-openshift-resources.sh | 22 - .../scripts/exec-openshift-tag-dockerhub.sh | 2 - .../scripts/exec-openshift-tag.sh | 2 - .../scripts/exec-pre-tasks-run.sh | 29 - .../scripts/exec-push-parallel-tug.sh | 6 - .../scripts/exec-push-parallel.sh | 6 - .../scripts/exec-tasks-run.sh | 28 - .../scripts/git-checkout-pull-merge.sh | 16 - .../scripts/git-checkout-pull.sh | 19 - images/oc-build-deploy-dind/tug.sh | 41 - images/oc-build-deploy-dind/tug/Dockerfile | 14 - .../tug/tug-build-push.sh | 66 - images/oc/Dockerfile | 63 - images/php/cli-drupal/Dockerfile | 16 - images/php/cli-drupal/drush.yml | 6 - images/php/cli-drupal/drushrc.php | 23 - images/php/cli/05-ssh-key.sh | 20 - images/php/cli/10-ssh-agent.sh | 13 - images/php/cli/55-cli-helpers.sh | 9 - images/php/cli/61-php-xdebug-cli-env.sh | 17 - images/php/cli/80-shell-timeout.sh | 7 - images/php/cli/90-composer-path.sh | 12 - images/php/cli/Dockerfile | 67 - images/php/cli/README.md | 19 - images/php/cli/id_ed25519_lagoon_cli.key | 7 - images/php/cli/ssh_config | 5 - images/php/fpm/00-lagoon-php.ini.tpl | 16 - images/php/fpm/Dockerfile | 114 - images/php/fpm/README.md | 1 - images/php/fpm/check_fcgi | 6 - images/php/fpm/entrypoints/50-ssmtp.sh | 48 - images/php/fpm/entrypoints/60-php-xdebug.sh | 46 - images/php/fpm/entrypoints/70-php-config.sh | 5 - images/php/fpm/entrypoints/71-php-newrelic.sh | 9 - images/php/fpm/php-fpm.d/www.conf | 119 - images/php/fpm/php.ini | 1587 -- images/php/fpm/ssmtp.conf | 4 - images/postgres-ckan/90-datastore-user.sh | 7 - images/postgres-ckan/Dockerfile | 12 - images/postgres-drupal/Dockerfile | 10 - images/postgres/Dockerfile | 40 - images/postgres/postgres-backup.sh | 79 - images/python-ckan/Dockerfile | 22 - images/python-ckandatapusher/Dockerfile | 34 - images/python/80-shell-timeout.sh | 7 - images/python/Dockerfile | 37 - images/rabbitmq-cluster/Dockerfile | 14 - images/rabbitmq-cluster/cluster-rabbit.sh | 17 - images/rabbitmq-cluster/enabled_plugins | 1 - images/rabbitmq-cluster/rabbitmq.conf | 13 - images/rabbitmq/Dockerfile | 11 - ...rabbitmq_delayed_message_exchange-3.7.0.ez | Bin 43805 -> 0 bytes images/redis-persistent/Dockerfile | 4 - images/redis/Dockerfile | 36 - images/redis/conf/ephemeral.conf | 4 - images/redis/conf/persistent.conf | 17 - images/redis/conf/redis.conf | 14 - images/redis/docker-entrypoint | 5 - images/solr-ckan/Dockerfile | 10 - images/solr-ckan/solr5.5/conf/elevate.xml | 27 - .../solr5.5/conf/mapping-ISOLatin1Accent.txt | 14 - images/solr-ckan/solr5.5/conf/protwords.txt | 7 - images/solr-ckan/solr5.5/conf/schema.xml | 188 - images/solr-ckan/solr5.5/conf/solrconfig.xml | 1800 -- .../solr5.5/conf/solrconfig_extra.xml | 80 - .../solr5.5/conf/solrcore.properties | 20 - images/solr-ckan/solr5.5/conf/stopwords.txt | 4 - images/solr-ckan/solr5.5/conf/synonyms.txt | 3 - images/solr-ckan/solr6.6/conf/elevate.xml | 27 - .../solr6.6/conf/mapping-ISOLatin1Accent.txt | 14 - images/solr-ckan/solr6.6/conf/protwords.txt | 7 - images/solr-ckan/solr6.6/conf/schema.xml | 188 - images/solr-ckan/solr6.6/conf/solrconfig.xml | 1494 -- .../solr6.6/conf/solrconfig_spellcheck.xml | 89 - .../solr6.6/conf/solrcore.properties | 20 - images/solr-ckan/solr6.6/conf/stopwords.txt | 4 - images/solr-ckan/solr6.6/conf/synonyms.txt | 3 - images/solr-drupal/Dockerfile | 10 - images/solr-drupal/solr5.5/conf/elevate.xml | 27 - .../solr5.5/conf/mapping-ISOLatin1Accent.txt | 14 - images/solr-drupal/solr5.5/conf/protwords.txt | 7 - images/solr-drupal/solr5.5/conf/schema.xml | 744 - .../solr5.5/conf/schema_extra_fields.xml | 23 - .../solr5.5/conf/schema_extra_types.xml | 34 - .../solr-drupal/solr5.5/conf/solrconfig.xml | 1800 -- .../solr5.5/conf/solrconfig_extra.xml | 80 - .../solr5.5/conf/solrcore.properties | 20 - images/solr-drupal/solr5.5/conf/stopwords.txt | 4 - images/solr-drupal/solr5.5/conf/synonyms.txt | 3 - images/solr-drupal/solr6.6/conf/elevate.xml | 27 - .../solr6.6/conf/mapping-ISOLatin1Accent.txt | 14 - images/solr-drupal/solr6.6/conf/protwords.txt | 7 - images/solr-drupal/solr6.6/conf/schema.xml | 843 - .../solr6.6/conf/schema_extra_fields.xml | 21 - .../solr6.6/conf/schema_extra_types.xml | 32 - .../solr6.6/conf/schema_legacy_fields.xml | 61 - .../solr6.6/conf/schema_legacy_types.xml | 14 - .../solr-drupal/solr6.6/conf/solrconfig.xml | 1494 -- .../solr6.6/conf/solrconfig_spellcheck.xml | 89 - .../solr6.6/conf/solrcore.properties | 20 - images/solr-drupal/solr6.6/conf/stopwords.txt | 4 - images/solr-drupal/solr6.6/conf/synonyms.txt | 3 - images/solr-drupal/solr7.5/conf/elevate.xml | 27 - .../solr7.5/conf/mapping-ISOLatin1Accent.txt | 14 - images/solr-drupal/solr7.5/conf/protwords.txt | 7 - images/solr-drupal/solr7.5/conf/schema.xml | 696 - .../solr7.5/conf/schema_extra_fields.xml | 13 - .../solr7.5/conf/schema_extra_types.xml | 59 - .../solr7.5/conf/schema_legacy_fields.xml | 61 - .../solr7.5/conf/schema_legacy_types.xml | 14 - .../solr-drupal/solr7.5/conf/solrconfig.xml | 1413 -- .../solr7.5/conf/solrconfig_extra.xml | 12 - .../solr7.5/conf/solrconfig_index.xml | 0 .../solr7.5/conf/solrconfig_spellcheck.xml | 89 - .../solr7.5/conf/solrcore.properties | 20 - images/solr-drupal/solr7.5/conf/stopwords.txt | 4 - images/solr-drupal/solr7.5/conf/synonyms.txt | 3 - images/solr/10-solr-port.sh | 9 - images/solr/20-solr-datadir.sh | 133 - images/solr/Dockerfile | 48 - images/varnish-drupal/Dockerfile | 6 - images/varnish-drupal/drupal.vcl | 448 - images/varnish-persistent-drupal/Dockerfile | 7 - images/varnish-persistent/Dockerfile | 7 - images/varnish/Dockerfile | 68 - images/varnish/default.vcl | 60 - images/varnish/docker-entrypoint | 3 - images/varnish/varnish-start.sh | 2 - images/yarn-workspace-builder/Dockerfile | 27 - jest.config.js | 15 - lagoon-remote/.lagoon.yml | 1 - lagoon-remote/README.md | 60 - lagoon-remote/docker-compose.yaml | 31 - lagoon-remote/docker-host | 1 - lagoon-remote/logs-collector | 1 - lagoon-remote/logs-forwarder | 1 - .../logs-forwarder-logstash/.lagoon.yml | 128 - .../logs-forwarder-logstash/Dockerfile | 17 - .../certs/lumberjack.cert | 17 - .../logs-forwarder-logstash/logstash.conf | 18 - lagoon-remote/logs-forwarder.remote.yml | 140 - local-dev/.dockerignore | 6 - local-dev/api-data-watcher-pusher/Dockerfile | 12 - .../api-data-watcher-pusher/api-watch-push.sh | 58 - .../api-data-watcher-pusher/create_jwt.sh | 12 - local-dev/api-data/00-clear-api-data.gql | 20 - local-dev/api-data/01-populate-api-data.gql | 1059 - local-dev/cli_id_ed25519 | 7 - local-dev/cli_id_ed25519.pub | 1 - local-dev/cli_id_rsa | 51 - local-dev/cli_id_rsa.pub | 1 - local-dev/git/Dockerfile | 33 - local-dev/git/authorized-keys.sh | 8 - local-dev/git/nginx/git | 14 - local-dev/git/service/fcgiwrap.sh | 2 - local-dev/git/service/nginx.sh | 2 - mkdocs.yml | 52 - node-packages/commons/.eslintignore | 1 - node-packages/commons/.eslintrc.js | 1 - node-packages/commons/.projectile | 0 .../commons/flow-typed/npm/flow-bin_v0.x.x.js | 6 - .../npm/lokka-transport-http_vx.x.x.js | 45 - .../commons/flow-typed/npm/lokka_vx.x.x.js | 52 - .../commons/flow-typed/npm/prettier_vx.x.x.js | 80 - node-packages/commons/jest.config.js | 7 - node-packages/commons/package.json | 33 - .../__tests__/__snapshots__/jwt.test.js.snap | 3 - .../commons/src/__tests__/jwt.test.js | 82 - node-packages/commons/src/api.js | 973 - node-packages/commons/src/gitlabApi.js | 98 - .../commons/src/jest-flow-transform.js | 26 - node-packages/commons/src/jwt.js | 103 - node-packages/commons/src/local-logging.js | 55 - node-packages/commons/src/logs.js | 73 - node-packages/commons/src/openshiftApi.js | 32 - node-packages/commons/src/tasks.js | 593 - node-packages/commons/src/types.js | 78 - .../eslint-config-lagoon-node/.eslintrc.js | 1 - .../eslint-config-lagoon-node/index.js | 66 - .../eslint-config-lagoon-node/package.json | 20 - .../clusterrole-daemonset-admin.yaml | 19 - .../clusterrole-openshiftbuilddeploy.yaml | 32 - openshift-setup/policybinding.yaml | 23 - openshift-setup/rolebinding.yaml | 14 - openshift-setup/router-template.cfg | 655 - openshift-setup/shared-resource-viewer.yaml | 36 - package.json | 23 - scripts/dev-galera.sh | 33 - scripts/test-host.sh | 139 - scripts/trigger_quay_builds.sh | 20 - services/api-db/.projectile | 0 services/api-db/Dockerfile | 16 - services/api-db/Dockerfile-galera | 10 - services/api-db/Makefile | 20 - .../docker-entrypoint-initdb.d/00-tables.sql | 203 - .../01-migrations.sql | 646 - .../docker-entrypoint-initdb.d/02-views.sql | 63 - .../03-procedures.sql | 484 - .../04-generate-ssh-key-fingerprints.sh | 38 - services/api-db/rerun_initdb.sh | 10 - services/api/.eslintrc.js | 1 - services/api/.gitignore | 1 - services/api/.lagoon.app.yml | 171 - services/api/.projectile | 2 - services/api/Dockerfile | 33 - services/api/ocaml-impl/Dockerfile | 27 - services/api/ocaml-impl/Makefile | 28 - services/api/ocaml-impl/README.md | 16 - services/api/ocaml-impl/api-next.install | 10 - services/api/ocaml-impl/api-next.opam | 16 - services/api/ocaml-impl/jbuild-workspace.dev | 1 - services/api/ocaml-impl/src/.merlin | 48 - services/api/ocaml-impl/src/jbuild | 6 - services/api/ocaml-impl/src/main.ml | 157 - services/api/package.json | 62 - services/api/src/apolloServer.js | 107 - services/api/src/app.js | 41 - services/api/src/authMiddleware.js | 107 - services/api/src/authMiddleware.test.js | 23 - services/api/src/clients/aws.js | 24 - services/api/src/clients/esClient.js | 13 - services/api/src/clients/keycloakClient.js | 11 - services/api/src/clients/kibanaClient.js | 16 - services/api/src/clients/pubSub.js | 79 - services/api/src/clients/searchguardClient.js | 12 - services/api/src/clients/sqlClient.js | 18 - services/api/src/index.js | 45 - services/api/src/logger.js | 17 - services/api/src/resolvers.js | 296 - services/api/src/resources/backup/events.js | 7 - .../api/src/resources/backup/resolvers.js | 287 - services/api/src/resources/backup/sql.js | 108 - .../__snapshots__/customer.test.js.snap | 11 - .../src/resources/customer/customer.test.js | 68 - .../api/src/resources/customer/helpers.js | 51 - .../api/src/resources/customer/resolvers.js | 202 - .../api/src/resources/customer/searchguard.js | 45 - services/api/src/resources/customer/sql.js | 63 - .../api/src/resources/deployment/events.js | 6 - .../api/src/resources/deployment/resolvers.js | 343 - services/api/src/resources/deployment/sql.js | 74 - .../src/resources/env-variables/resolvers.js | 235 - .../api/src/resources/env-variables/sql.js | 69 - .../__snapshots__/environment.test.js.snap | 5 - .../resources/environment/environment.test.js | 24 - .../api/src/resources/environment/helpers.js | 15 - .../src/resources/environment/resolvers.js | 684 - services/api/src/resources/environment/sql.js | 57 - .../src/resources/environment/validators.js | 72 - services/api/src/resources/file/resolvers.js | 152 - services/api/src/resources/file/sql.js | 69 - services/api/src/resources/index.js | 69 - .../__snapshots__/notification.test.js.snap | 17 - .../api/src/resources/notification/helpers.js | 61 - .../notification/notification.test.js | 109 - .../src/resources/notification/resolvers.js | 379 - .../api/src/resources/notification/sql.js | 161 - .../__snapshots__/openshift.test.js.snap | 5 - .../src/resources/openshift/openshift.test.js | 25 - .../api/src/resources/openshift/resolvers.js | 163 - services/api/src/resources/openshift/sql.js | 29 - .../__snapshots__/project.test.js.snap | 7 - services/api/src/resources/project/helpers.js | 122 - .../api/src/resources/project/keycloak.js | 53 - .../api/src/resources/project/project.test.js | 34 - .../api/src/resources/project/resolvers.js | 462 - .../api/src/resources/project/searchguard.js | 106 - services/api/src/resources/project/sql.js | 106 - .../sshKey/__snapshots__/sshKey.test.js.snap | 5 - services/api/src/resources/sshKey/index.js | 25 - .../api/src/resources/sshKey/resolvers.js | 222 - services/api/src/resources/sshKey/sql.js | 112 - .../api/src/resources/sshKey/sshKey.test.js | 41 - services/api/src/resources/task/events.js | 6 - services/api/src/resources/task/helpers.js | 117 - services/api/src/resources/task/resolvers.js | 435 - services/api/src/resources/task/sql.js | 74 - services/api/src/resources/user/helpers.js | 15 - services/api/src/resources/user/keycloak.js | 200 - services/api/src/resources/user/resolvers.js | 592 - services/api/src/resources/user/sql.js | 152 - services/api/src/routes/index.js | 28 - services/api/src/routes/keys.js | 71 - services/api/src/routes/notFound.js | 9 - services/api/src/routes/status.js | 10 - services/api/src/schema.js | 10 - services/api/src/server.js | 37 - services/api/src/typeDefs.js | 957 - services/api/src/util/auth.js | 202 - services/api/src/util/db.js | 118 - services/api/src/util/db.test.js | 35 - services/api/src/util/gql.js | 20 - services/api/src/util/pickNonNil.js | 10 - services/api/src/util/snakeCase.js | 49 - services/api/src/util/waitAndInitKeycloak.js | 62 - services/api/wait-for-mariadb.sh | 9 - services/auth-server/.babelrc | 8 - services/auth-server/.dockerignore | 4 - services/auth-server/.eslintignore | 1 - services/auth-server/.eslintrc.js | 1 - services/auth-server/.gitignore | 2 - services/auth-server/.lagoon.app.yml | 125 - services/auth-server/.projectile | 0 services/auth-server/Dockerfile | 29 - services/auth-server/README.md | 35 - services/auth-server/package.json | 37 - services/auth-server/src/index.js | 36 - services/auth-server/src/logger.js | 17 - services/auth-server/src/routes.js | 65 - services/auth-server/src/util/db.js | 84 - services/auth-server/src/util/routing.js | 57 - services/auth-server/test/test-flow | 10 - services/auth-server/test/test-lint | 10 - services/auto-idler/.lagoon.yml | 180 - services/auto-idler/Dockerfile | 17 - services/auto-idler/create_jwt.sh | 12 - services/auto-idler/idle-clis.sh | 102 - services/auto-idler/idle-services.sh | 107 - services/broker-single/Dockerfile | 2 - services/broker/.lagoon.app.yml | 141 - services/broker/Dockerfile | 2 - services/docker-host/docker-host.yaml | 126 - services/drush-alias/.lagoon.app.yml | 137 - services/drush-alias/Dockerfile | 4 - services/drush-alias/README.md | 13 - services/drush-alias/docker-compose.yml | 21 - services/drush-alias/nginx.conf | 7 - services/drush-alias/testing/Dockerfile | 10 - .../drush-alias/testing/aliases.drushrc.php | 6 - services/drush-alias/testing/entrypoint.sh | 9 - .../drush-alias/web/aliases.drushrc.php.stub | 294 - services/drush-alias/web/index.html | 50 - services/keycloak-db/Dockerfile | 8 - services/keycloak-db/Dockerfile-galera | 8 - services/keycloak/.lagoon.app.yml | 154 - services/keycloak/Dockerfile | 58 - services/keycloak/start.sh | 96 - services/keycloak/wait-for-mariadb.sh | 9 - services/logs-collector/.lagoon.yml | 292 - services/logs-db-curator/.lagoon.app.yml | 89 - .../logs-db-curator/90-generate-http-auth.sh | 4 - services/logs-db-curator/Dockerfile | 9 - services/logs-db-curator/actions.yml | 96 - services/logs-db-curator/curator.yml | 12 - services/logs-db-ui/.lagoon.yml | 126 - services/logs-db-ui/Dockerfile | 61 - services/logs-db-ui/README.md | 5 - .../entrypoints/80-keycloak-url.bash | 15 - .../entrypoints/81-logs-db-ui-url.bash | 15 - .../90-keycloak-client-secret.bash | 60 - services/logs-db/.lagoon.cluster.yml | 242 - services/logs-db/.lagoon.single.yml | 113 - services/logs-db/Dockerfile | 29 - services/logs-db/README.md | 5 - .../logs-db/entrypoints/80-keycloak-url.bash | 15 - services/logs-db/es-curl | 14 - services/logs-db/sgconfig/sg_config.yml | 106 - .../logs-db/sgconfig/sg_internal_users.yml | 15 - .../logs-db/sgconfig/sg_roles_mapping.yml | 20 - services/logs-db/start.sh | 37 - services/logs-forwarder/.lagoon.multi.yml | 324 - services/logs-forwarder/.lagoon.single.yml | 307 - services/logs-forwarder/Dockerfile | 29 - services/logs-forwarder/ca_cert.pem | 19 - services/logs-forwarder/ca_key.pem | 30 - services/logs-forwarder/entrypoint.sh | 16 - services/logs2logs-db/.lagoon.yml | 198 - services/logs2logs-db/Dockerfile | 36 - services/logs2logs-db/README.md | 5 - services/logs2logs-db/certs/lumberjack.cert | 17 - services/logs2logs-db/certs/lumberjack.key | 28 - ...gstash-enable-forward-external-logstash.sh | 29 - services/logs2logs-db/pipeline/debug.conf | 12 - .../logs2logs-db/pipeline/lagoon-logs.conf | 56 - .../pipeline/router-application-logs.conf | 120 - .../logs2logs-db/pipeline/service-logs.conf | 37 - services/logs2logs-db/pipelines.yml | 8 - .../templates/application-logs.json | 48 - .../logs2logs-db/templates/lagoon-logs.json | 48 - .../logs2logs-db/templates/router-logs.json | 48 - .../logs2logs-db/templates/service-logs.json | 48 - services/logs2rocketchat/.babelrc | 9 - services/logs2rocketchat/.flowconfig | 7 - services/logs2rocketchat/.gitignore | 2 - services/logs2rocketchat/.lagoon.app.yml | 109 - services/logs2rocketchat/.projectile | 0 services/logs2rocketchat/Dockerfile | 29 - services/logs2rocketchat/LICENSE.md | 11 - services/logs2rocketchat/README.md | 1 - .../npm/amqp-connection-manager_vx.x.x.js | 53 - .../flow-typed/npm/amqplib_vx.x.x.js | 410 - .../flow-typed/npm/babel-cli_vx.x.x.js | 108 - .../flow-typed/npm/babel-core_vx.x.x.js | 192 - ...el-plugin-syntax-async-functions_vx.x.x.js | 32 - ...lugin-transform-flow-strip-types_vx.x.x.js | 32 - ...bel-plugin-transform-regenerator_vx.x.x.js | 32 - .../npm/babel-preset-es2015_vx.x.x.js | 32 - .../flow-typed/npm/bl_vx.x.x.js | 39 - .../npm/buffer-equal-constant-time_vx.x.x.js | 38 - .../flow-typed/npm/flow-bin_v0.x.x.js | 6 - .../flow-typed/npm/jest_v18.x.x.js | 439 - .../npm/loggly-winston-bulk_vx.x.x.js | 39 - .../flow-typed/npm/newman_vx.x.x.js | 388 - .../flow-typed/npm/nodemon_vx.x.x.js | 214 - .../flow-typed/npm/winston_vx.x.x.js | 214 - services/logs2rocketchat/package.json | 21 - services/logs2rocketchat/src/index.js | 28 - .../logs2rocketchat/src/readFromRabbitMQ.js | 253 - services/logs2rocketchat/src/types.js | 10 - services/logs2slack/.gitignore | 2 - services/logs2slack/.lagoon.app.yml | 109 - services/logs2slack/.projectile | 0 services/logs2slack/Dockerfile | 29 - services/logs2slack/LICENSE.md | 11 - services/logs2slack/README.md | 2 - .../npm/amqp-connection-manager_vx.x.x.js | 53 - .../flow-typed/npm/amqplib_vx.x.x.js | 410 - .../flow-typed/npm/babel-cli_vx.x.x.js | 108 - .../flow-typed/npm/babel-core_vx.x.x.js | 192 - ...el-plugin-syntax-async-functions_vx.x.x.js | 32 - ...lugin-transform-flow-strip-types_vx.x.x.js | 32 - ...bel-plugin-transform-regenerator_vx.x.x.js | 32 - .../npm/babel-preset-es2015_vx.x.x.js | 32 - .../logs2slack/flow-typed/npm/bl_vx.x.x.js | 39 - .../npm/buffer-equal-constant-time_vx.x.x.js | 38 - .../flow-typed/npm/flow-bin_v0.x.x.js | 6 - .../logs2slack/flow-typed/npm/jest_v18.x.x.js | 439 - .../npm/loggly-winston-bulk_vx.x.x.js | 39 - .../flow-typed/npm/newman_vx.x.x.js | 388 - .../flow-typed/npm/nodemon_vx.x.x.js | 214 - .../flow-typed/npm/winston_vx.x.x.js | 214 - services/logs2slack/package.json | 22 - services/logs2slack/src/index.js | 28 - services/logs2slack/src/readFromRabbitMQ.js | 131 - services/logs2slack/src/types.js | 10 - services/openshiftbuilddeploy/.gitignore | 2 - services/openshiftbuilddeploy/.lagoon.app.yml | 109 - services/openshiftbuilddeploy/.projectile | 0 services/openshiftbuilddeploy/Dockerfile | 29 - services/openshiftbuilddeploy/LICENSE.md | 11 - services/openshiftbuilddeploy/README.md | 2 - services/openshiftbuilddeploy/package.json | 28 - services/openshiftbuilddeploy/src/index.js | 524 - .../openshiftbuilddeploymonitor/.gitignore | 2 - .../.lagoon.app.yml | 109 - .../openshiftbuilddeploymonitor/.projectile | 0 .../openshiftbuilddeploymonitor/Dockerfile | 29 - .../openshiftbuilddeploymonitor/LICENSE.md | 11 - .../openshiftbuilddeploymonitor/README.md | 2 - .../openshiftbuilddeploymonitor/package.json | 29 - .../openshiftbuilddeploymonitor/src/index.js | 341 - services/openshiftjobs/.gitignore | 2 - services/openshiftjobs/.lagoon.app.yml | 109 - services/openshiftjobs/.projectile | 0 services/openshiftjobs/Dockerfile | 30 - services/openshiftjobs/LICENSE.md | 11 - services/openshiftjobs/package.json | 25 - services/openshiftjobs/src/index.js | 315 - services/openshiftjobsmonitor/.gitignore | 2 - services/openshiftjobsmonitor/.lagoon.app.yml | 109 - services/openshiftjobsmonitor/.projectile | 0 services/openshiftjobsmonitor/Dockerfile | 29 - services/openshiftjobsmonitor/LICENSE.md | 11 - services/openshiftjobsmonitor/package.json | 25 - services/openshiftjobsmonitor/src/index.js | 322 - services/openshiftmisc/.gitignore | 2 - services/openshiftmisc/.lagoon.app.yml | 109 - services/openshiftmisc/.projectile | 0 services/openshiftmisc/Dockerfile | 29 - services/openshiftmisc/LICENSE.md | 11 - services/openshiftmisc/package.json | 25 - .../src/handlers/resticRestore.js | 104 - services/openshiftmisc/src/index.js | 83 - services/openshiftremove/.gitignore | 2 - services/openshiftremove/.lagoon.app.yml | 109 - services/openshiftremove/.projectile | 0 services/openshiftremove/Dockerfile | 29 - services/openshiftremove/LICENSE.md | 11 - services/openshiftremove/README.md | 29 - services/openshiftremove/package.json | 25 - services/openshiftremove/src/index.js | 379 - services/rest2tasks/.gitignore | 2 - services/rest2tasks/.lagoon.app.yml | 152 - services/rest2tasks/.projectile | 0 services/rest2tasks/Dockerfile | 29 - services/rest2tasks/README.md | 1 - services/rest2tasks/package.json | 24 - services/rest2tasks/src/index.js | 313 - services/ssh/.lagoon.app.yml | 143 - services/ssh/.projectile | 0 services/ssh/Dockerfile | 105 - services/ssh/README.md | 19 - services/ssh/authorize.sh | 37 - services/ssh/create_60_sec_jwt.sh | 12 - services/ssh/docker-entrypoint.sh | 14 - services/ssh/etc/libnss-mysql-root.cfg | 2 - services/ssh/etc/libnss-mysql.cfg | 21 - services/ssh/etc/nsswitch.conf | 20 - services/ssh/etc/ssh/sshd_config | 42 - services/ssh/home/command.sh | 31 - services/ssh/home/rsh.sh | 140 - services/ssh/home/token.sh | 34 - services/ssh/libnss-mysql-1.5.tar.gz | Bin 333385 -> 0 bytes services/storage-calculator/.lagoon.yml | 102 - services/storage-calculator/Dockerfile | 17 - .../storage-calculator/calculate-storage.sh | 146 - services/storage-calculator/create_jwt.sh | 12 - services/ui/.env.defaults | 3 - services/ui/.env.local | 6 - services/ui/.env.schema | 10 - services/ui/.gitignore | 9 - services/ui/.lagoon.app.yml | 151 - services/ui/Dockerfile | 29 - services/ui/package.json | 47 - services/ui/server.js | 87 - services/ui/src/.babelrc | 14 - .../AddTask/components/Completed.js | 3 - .../AddTask/components/DrushArchiveDump.js | 96 - .../AddTask/components/DrushCacheClear.js | 96 - .../AddTask/components/DrushRsyncFiles.js | 127 - .../AddTask/components/DrushSqlDump.js | 96 - .../AddTask/components/DrushSqlSync.js | 127 - .../components/AddTask/components/Empty.js | 4 - .../components/AddTask/components/Error.js | 3 - .../components/AddTask/components/logic.js | 36 - services/ui/src/components/AddTask/index.js | 108 - services/ui/src/components/AddTask/logic.js | 110 - services/ui/src/components/Backups/index.js | 175 - .../src/components/Breadcrumbs/Breadcrumb.js | 64 - .../src/components/Breadcrumbs/Environment.js | 17 - .../ui/src/components/Breadcrumbs/Project.js | 17 - .../ui/src/components/Breadcrumbs/index.js | 20 - .../ui/src/components/DeleteConfirm/index.js | 106 - .../ui/src/components/DeleteConfirm/logic.js | 22 - .../ui/src/components/Deployment/index.js | 188 - .../ui/src/components/Deployments/index.js | 174 - .../ui/src/components/Environment/index.js | 214 - .../ui/src/components/Environments/index.js | 175 - services/ui/src/components/Footer/index.js | 16 - services/ui/src/components/Header/index.js | 70 - services/ui/src/components/LogViewer/index.js | 38 - services/ui/src/components/Modal/index.js | 60 - services/ui/src/components/NavTabs/index.js | 178 - .../components/ProjectDetailsSidebar/index.js | 243 - services/ui/src/components/Projects/index.js | 194 - .../src/components/RestoreButton/Prepare.js | 38 - .../ui/src/components/RestoreButton/index.js | 17 - services/ui/src/components/Task/index.js | 179 - services/ui/src/components/Tasks/index.js | 168 - services/ui/src/components/link/Backups.js | 27 - services/ui/src/components/link/Deployment.js | 31 - .../ui/src/components/link/Deployments.js | 27 - .../ui/src/components/link/Environment.js | 27 - services/ui/src/components/link/Project.js | 26 - services/ui/src/components/link/Task.js | 31 - services/ui/src/components/link/Tasks.js | 27 - services/ui/src/components/style/Box.js | 50 - services/ui/src/layouts/global.js | 159 - services/ui/src/layouts/main.js | 11 - services/ui/src/layouts/status.js | 30 - services/ui/src/lib/ApiConnection.js | 83 - services/ui/src/lib/Authenticator.js | 20 - services/ui/src/lib/fragment/Backup.js | 16 - services/ui/src/lib/fragment/Deployment.js | 20 - services/ui/src/lib/fragment/Task.js | 28 - .../ui/src/lib/mutation/DeleteEnvironment.js | 7 - services/ui/src/lib/polyfills.js | 14 - services/ui/src/lib/query/AllProjects.js | 16 - .../EnvironmentByOpenshiftProjectName.js | 22 - .../src/lib/query/EnvironmentWithBackups.js | 22 - .../lib/query/EnvironmentWithDeployment.js | 23 - .../lib/query/EnvironmentWithDeployments.js | 22 - .../ui/src/lib/query/EnvironmentWithTask.js | 32 - .../ui/src/lib/query/EnvironmentWithTasks.js | 31 - services/ui/src/lib/query/ProjectByName.js | 29 - services/ui/src/lib/subscription/Backups.js | 11 - .../ui/src/lib/subscription/Deployments.js | 11 - services/ui/src/lib/subscription/Tasks.js | 11 - services/ui/src/lib/variables.js | 68 - services/ui/src/lib/withKeycloak.js | 57 - services/ui/src/lib/withLocalAuth.js | 30 - services/ui/src/next.config.js | 53 - services/ui/src/pages/_app.js | 51 - services/ui/src/pages/_error.js | 45 - services/ui/src/pages/_loading.js | 11 - services/ui/src/pages/backups.js | 146 - services/ui/src/pages/deployment.js | 101 - services/ui/src/pages/deployments.js | 130 - services/ui/src/pages/environment.js | 81 - services/ui/src/pages/index.js | 16 - services/ui/src/pages/project.js | 114 - services/ui/src/pages/projects.js | 63 - services/ui/src/pages/task.js | 98 - services/ui/src/pages/tasks.js | 125 - .../ui/src/static/images/backups-active.svg | 1 - services/ui/src/static/images/backups.svg | 1 - services/ui/src/static/images/branches.svg | 1 - services/ui/src/static/images/command.svg | 1 - .../src/static/images/containers-active.svg | 1 - services/ui/src/static/images/containers.svg | 1 - services/ui/src/static/images/copy.svg | 1 - services/ui/src/static/images/created.svg | 1 - .../src/static/images/deployments-active.svg | 1 - services/ui/src/static/images/deployments.svg | 1 - services/ui/src/static/images/duration.png | Bin 1284 -> 0 bytes services/ui/src/static/images/duration.svg | 1 - .../images/environment-branch-hover.svg | 1 - .../src/static/images/environment-branch.svg | 1 - .../images/environment-pull-request-hover.svg | 1 - .../images/environment-pull-request.svg | 1 - .../ui/src/static/images/environments.svg | 1 - .../ui/src/static/images/events-active.svg | 1 - services/ui/src/static/images/events.svg | 1 - services/ui/src/static/images/failed.svg | 1 - services/ui/src/static/images/git-lab.svg | 1 - services/ui/src/static/images/git.svg | 1 - services/ui/src/static/images/header.png | Bin 10453 -> 0 bytes services/ui/src/static/images/in-progress.svg | 1 - services/ui/src/static/images/last-deploy.svg | 1 - services/ui/src/static/images/members.svg | 1 - .../ui/src/static/images/overview-active.svg | 1 - services/ui/src/static/images/overview.svg | 1 - services/ui/src/static/images/pending.svg | 1 - .../ui/src/static/images/profile-dropdown.svg | 1 - .../ui/src/static/images/pull-request.svg | 1 - services/ui/src/static/images/right-arrow.svg | 1 - services/ui/src/static/images/search.png | Bin 944 -> 0 bytes services/ui/src/static/images/service.svg | 1 - services/ui/src/static/images/successful.svg | 1 - .../ui/src/static/images/tasks-active.svg | 1 - services/ui/src/static/images/tasks.svg | 1 - services/ui/src/static/images/url.svg | 1 - services/ui/src/static/normalize.css | 447 - services/webhook-handler/.env | 1 - services/webhook-handler/.gitignore | 2 - services/webhook-handler/.lagoon.app.yml | 147 - services/webhook-handler/.projectile | 0 .../webhook-handler/.vscode/settings.json | 4 - services/webhook-handler/Dockerfile | 29 - services/webhook-handler/LICENSE.md | 11 - services/webhook-handler/README.md | 38 - services/webhook-handler/docker-compose.yaml | 23 - .../npm/amqp-connection-manager_vx.x.x.js | 53 - .../flow-typed/npm/amqplib_vx.x.x.js | 410 - .../flow-typed/npm/babel-cli_vx.x.x.js | 108 - .../flow-typed/npm/babel-core_vx.x.x.js | 192 - ...el-plugin-syntax-async-functions_vx.x.x.js | 32 - ...lugin-transform-flow-strip-types_vx.x.x.js | 32 - ...bel-plugin-transform-regenerator_vx.x.x.js | 32 - .../npm/babel-preset-es2015_vx.x.x.js | 32 - .../flow-typed/npm/bl_vx.x.x.js | 39 - .../npm/buffer-equal-constant-time_vx.x.x.js | 38 - .../flow-typed/npm/flow-bin_v0.x.x.js | 6 - .../npm/flow-remove-types_vx.x.x.js | 38 - .../flow-typed/npm/jest_v18.x.x.js | 439 - .../npm/loggly-winston-bulk_vx.x.x.js | 39 - .../flow-typed/npm/newman_vx.x.x.js | 388 - .../flow-typed/npm/nodemon_vx.x.x.js | 214 - .../flow-typed/npm/winston_vx.x.x.js | 214 - services/webhook-handler/jest.config.js | 7 - ...on-webhook-handler.postman_collection.json | 346 - .../newman/localhost.postman_environment.json | 16 - services/webhook-handler/package.json | 31 - .../src/__tests__/extractWebhookData-test.js | 231 - .../webhook-handler/src/createReqHandler.js | 93 - .../webhook-handler/src/extractWebhookData.js | 154 - services/webhook-handler/src/index.js | 58 - .../src/jest-flow-transform.js | 26 - .../src/sendToLagoonWebhooks.js | 35 - services/webhook-handler/src/types.js | 92 - services/webhooks2tasks/.gitignore | 2 - services/webhooks2tasks/.lagoon.app.yml | 109 - services/webhooks2tasks/.projectile | 0 services/webhooks2tasks/.vscode/settings.json | 4 - services/webhooks2tasks/Dockerfile | 29 - services/webhooks2tasks/LICENSE.md | 11 - services/webhooks2tasks/README.md | 29 - .../npm/amqp-connection-manager_vx.x.x.js | 53 - .../flow-typed/npm/amqplib_vx.x.x.js | 410 - .../flow-typed/npm/babel-cli_vx.x.x.js | 108 - .../flow-typed/npm/babel-core_vx.x.x.js | 192 - ...el-plugin-syntax-async-functions_vx.x.x.js | 32 - ...lugin-transform-flow-strip-types_vx.x.x.js | 32 - ...bel-plugin-transform-regenerator_vx.x.x.js | 32 - .../npm/babel-preset-es2015_vx.x.x.js | 32 - .../flow-typed/npm/bl_vx.x.x.js | 39 - .../npm/buffer-equal-constant-time_vx.x.x.js | 38 - .../flow-typed/npm/flow-bin_v0.x.x.js | 6 - .../flow-typed/npm/jest_v18.x.x.js | 439 - .../npm/loggly-winston-bulk_vx.x.x.js | 39 - .../flow-typed/npm/newman_vx.x.x.js | 388 - .../flow-typed/npm/nodemon_vx.x.x.js | 214 - .../flow-typed/npm/winston_vx.x.x.js | 214 - services/webhooks2tasks/package.json | 27 - .../src/handlers/bitbucketBranchDeleted.js | 64 - .../handlers/bitbucketPullRequestClosed.js | 66 - .../handlers/bitbucketPullRequestUpdated.js | 72 - .../src/handlers/bitbucketPush.js | 84 - .../src/handlers/githubBranchDeleted.js | 62 - .../src/handlers/githubPullRequestClosed.js | 67 - .../src/handlers/githubPullRequestOpened.js | 72 - .../handlers/githubPullRequestSynchronize.js | 91 - .../webhooks2tasks/src/handlers/githubPush.js | 83 - .../src/handlers/gitlabBranchDeleted.js | 66 - .../src/handlers/gitlabGroupCreate.js | 48 - .../src/handlers/gitlabGroupDelete.js | 44 - .../src/handlers/gitlabGroupUpdate.js | 50 - .../src/handlers/gitlabProjectCreate.js | 63 - .../src/handlers/gitlabProjectDelete.js | 47 - .../src/handlers/gitlabProjectUpdate.js | 116 - .../src/handlers/gitlabPullRequestClosed.js | 66 - .../src/handlers/gitlabPullRequestOpened.js | 73 - .../src/handlers/gitlabPullRequestUpdated.js | 74 - .../webhooks2tasks/src/handlers/gitlabPush.js | 84 - .../src/handlers/gitlabSshKeyAdd.js | 74 - .../src/handlers/gitlabSshKeyRemove.js | 56 - .../src/handlers/gitlabUserCreate.js | 55 - .../src/handlers/gitlabUserCustomerAdd.js | 52 - .../src/handlers/gitlabUserCustomerRemove.js | 45 - .../src/handlers/gitlabUserDelete.js | 44 - .../src/handlers/gitlabUserProjectAdd.js | 45 - .../src/handlers/gitlabUserProjectRemove.js | 45 - .../src/handlers/gitlabUserUpdate.js | 60 - .../handlers/resticbackupRestoreFinished.js | 62 - .../handlers/resticbackupSnapshotFinished.js | 117 - .../handlers/resticbackupSnapshotPruned.js | 88 - services/webhooks2tasks/src/index.js | 48 - services/webhooks2tasks/src/processQueue.js | 30 - services/webhooks2tasks/src/types.js | 50 - .../webhooks2tasks/src/webhooks/backup.js | 87 - .../webhooks2tasks/src/webhooks/dataSync.js | 136 - .../webhooks2tasks/src/webhooks/projects.js | 343 - tests/Dockerfile | 17 - tests/ansible.cfg | 5 - tests/checks/check-api-request.yaml | 11 - tests/checks/check-branch-sha.yaml | 35 - tests/checks/check-deployed.yaml | 53 - tests/checks/check-dot-env.yaml | 1 - tests/checks/check-json-content.yaml | 11 - tests/checks/check-pullrequest.yaml | 80 - tests/checks/check-url-content-absent.yaml | 9 - .../check-url-content-basic-auth-host.yaml | 14 - .../checks/check-url-content-basic-auth.yaml | 13 - tests/checks/check-url-content-host.yaml | 12 - tests/checks/check-url-content.yaml | 11 - tests/checks/check-url-header-absent.yaml | 9 - tests/checks/check-url-header.yaml | 12 - tests/checks/check-url-redirect-host.yaml | 14 - tests/checks/check-url-redirect.yaml | 13 - tests/checks/check-url-returncode-host.yaml | 13 - tests/checks/check-url-returncode.yaml | 12 - tests/entrypoint.sh | 15 - .../php5.6/Dockerfile.builder | 9 - .../php5.6/Dockerfile.mariadb | 2 - .../php5.6/Dockerfile.nginx | 9 - .../drupal8-dockerfiles/php5.6/Dockerfile.php | 7 - .../php5.6/Dockerfile.postgres | 2 - .../php5.6/Dockerfile.redis | 2 - .../php5.6/Dockerfile.solr | 3 - .../php5.6/Dockerfile.varnish | 2 - .../php7.0/Dockerfile.builder | 19 - .../php7.0/Dockerfile.mariadb | 2 - .../php7.0/Dockerfile.nginx | 9 - .../drupal8-dockerfiles/php7.0/Dockerfile.php | 7 - .../php7.0/Dockerfile.postgres | 2 - .../php7.0/Dockerfile.redis | 2 - .../php7.0/Dockerfile.solr | 3 - .../php7.0/Dockerfile.varnish | 2 - .../php7.1/Dockerfile.builder | 9 - .../php7.1/Dockerfile.mariadb | 2 - .../php7.1/Dockerfile.nginx | 9 - .../drupal8-dockerfiles/php7.1/Dockerfile.php | 7 - .../php7.1/Dockerfile.postgres | 2 - .../php7.1/Dockerfile.redis | 2 - .../php7.1/Dockerfile.solr | 3 - .../php7.1/Dockerfile.varnish | 2 - .../php7.2-galera/Dockerfile.builder | 9 - .../php7.2-galera/Dockerfile.mariadb | 2 - .../php7.2-galera/Dockerfile.nginx | 9 - .../php7.2-galera/Dockerfile.php | 7 - .../php7.2-galera/Dockerfile.redis | 2 - .../php7.2-galera/Dockerfile.solr | 3 - .../php7.2-galera/Dockerfile.varnish | 2 - .../php7.2/Dockerfile.builder | 9 - .../php7.2/Dockerfile.mariadb | 2 - .../php7.2/Dockerfile.nginx | 9 - .../drupal8-dockerfiles/php7.2/Dockerfile.php | 7 - .../php7.2/Dockerfile.postgres | 2 - .../php7.2/Dockerfile.redis | 2 - .../php7.2/Dockerfile.solr | 3 - .../php7.2/Dockerfile.varnish | 2 - .../php7.3/Dockerfile.builder | 9 - .../php7.3/Dockerfile.mariadb | 2 - .../php7.3/Dockerfile.nginx | 9 - .../drupal8-dockerfiles/php7.3/Dockerfile.php | 7 - .../php7.3/Dockerfile.postgres | 2 - .../php7.3/Dockerfile.redis | 2 - .../php7.3/Dockerfile.solr | 3 - .../php7.3/Dockerfile.varnish | 2 - tests/files/drupal8-mariadb/.dockerignore | 2 - tests/files/drupal8-mariadb/.gitignore | 21 - tests/files/drupal8-mariadb/.lagoon.yml | 53 - tests/files/drupal8-mariadb/LICENSE | 339 - tests/files/drupal8-mariadb/README.md | 116 - tests/files/drupal8-mariadb/composer.json | 79 - tests/files/drupal8-mariadb/composer.lock | 6400 ------ .../drupal8-mariadb/config/sync/.gitkeep | 0 .../files/drupal8-mariadb/docker-compose.yml | 86 - tests/files/drupal8-mariadb/drush/README.md | 1 - .../drupal8-mariadb/drush/aliases.drushrc.php | 15 - tests/files/drupal8-mariadb/drush/drushrc.php | 14 - .../drupal8-mariadb/drush/policy.drush.inc | 38 - .../scripts/composer/ScriptHandler.php | 84 - tests/files/drupal8-mariadb/web/.csslintrc | 40 - tests/files/drupal8-mariadb/web/.editorconfig | 17 - tests/files/drupal8-mariadb/web/.eslintignore | 9 - .../files/drupal8-mariadb/web/.eslintrc.json | 3 - .../files/drupal8-mariadb/web/.gitattributes | 57 - tests/files/drupal8-mariadb/web/.htaccess | 189 - tests/files/drupal8-mariadb/web/autoload.php | 17 - tests/files/drupal8-mariadb/web/index.php | 22 - .../drupal8-mariadb/web/modules/.gitkeep | 0 .../drupal8-mariadb/web/profiles/.gitkeep | 0 tests/files/drupal8-mariadb/web/robots.txt | 61 - .../web/sites/default/all.services.yml | 4 - .../web/sites/default/all.settings.php | 15 - .../web/sites/default/default.services.yml | 174 - .../web/sites/default/default.settings.php | 765 - .../sites/default/development.services.yml | 15 - .../sites/default/development.settings.php | 29 - .../sites/default/example.settings.local.php | 12 - .../web/sites/default/production.services.yml | 11 - .../web/sites/default/production.settings.php | 24 - .../web/sites/default/settings.php | 127 - .../web/sites/example.sites.php | 55 - .../files/drupal8-mariadb/web/themes/.gitkeep | 0 tests/files/drupal8-mariadb/web/update.php | 31 - tests/files/drupal8-mariadb/web/web.config | 103 - tests/files/drupal8-postgres/.dockerignore | 2 - tests/files/drupal8-postgres/.gitignore | 21 - tests/files/drupal8-postgres/.lagoon.yml | 46 - tests/files/drupal8-postgres/LICENSE | 339 - tests/files/drupal8-postgres/README.md | 116 - tests/files/drupal8-postgres/composer.json | 79 - tests/files/drupal8-postgres/composer.lock | 6400 ------ .../drupal8-postgres/config/sync/.gitkeep | 0 .../files/drupal8-postgres/docker-compose.yml | 84 - tests/files/drupal8-postgres/drush/README.md | 1 - .../drush/aliases.drushrc.php | 15 - .../files/drupal8-postgres/drush/drushrc.php | 14 - .../drupal8-postgres/drush/policy.drush.inc | 38 - .../scripts/composer/ScriptHandler.php | 84 - tests/files/drupal8-postgres/web/.csslintrc | 40 - .../files/drupal8-postgres/web/.editorconfig | 17 - .../files/drupal8-postgres/web/.eslintignore | 9 - .../files/drupal8-postgres/web/.eslintrc.json | 3 - .../files/drupal8-postgres/web/.gitattributes | 57 - tests/files/drupal8-postgres/web/.htaccess | 189 - tests/files/drupal8-postgres/web/autoload.php | 17 - tests/files/drupal8-postgres/web/index.php | 22 - .../drupal8-postgres/web/modules/.gitkeep | 0 .../drupal8-postgres/web/profiles/.gitkeep | 0 tests/files/drupal8-postgres/web/robots.txt | 61 - .../web/sites/default/all.services.yml | 4 - .../web/sites/default/all.settings.php | 15 - .../web/sites/default/default.services.yml | 174 - .../web/sites/default/default.settings.php | 765 - .../sites/default/development.services.yml | 15 - .../sites/default/development.settings.php | 29 - .../sites/default/example.settings.local.php | 12 - .../web/sites/default/production.services.yml | 11 - .../web/sites/default/production.settings.php | 24 - .../web/sites/default/settings.php | 127 - .../web/sites/example.sites.php | 55 - .../drupal8-postgres/web/themes/.gitkeep | 0 tests/files/drupal8-postgres/web/update.php | 31 - tests/files/drupal8-postgres/web/web.config | 103 - tests/files/elasticsearch-cluster/.lagoon.yml | 4 - .../Dockerfile.elasticsearch | 2 - .../elasticsearch-cluster/Dockerfile.nginx | 4 - tests/files/elasticsearch-cluster/app.conf | 10 - .../elasticsearch-cluster/docker-compose.yml | 23 - tests/files/elasticsearch/.lagoon.yml | 4 - .../elasticsearch/Dockerfile.elasticsearch | 2 - tests/files/elasticsearch/Dockerfile.nginx | 4 - tests/files/elasticsearch/app.conf | 10 - tests/files/elasticsearch/docker-compose.yml | 23 - .../.dockerignore | 1 - .../.lagoon.yml | 15 - .../Dockerfile | 18 - .../docker-compose.yml | 23 - .../index.js | 24 - .../package.json | 12 - .../yarn.lock | 247 - .../.dockerignore | 1 - .../.lagoon.yml | 1 - .../Dockerfile | 18 - .../docker-compose.yml | 23 - .../features-disable-inject-git-sha/index.js | 24 - .../package.json | 12 - .../features-disable-inject-git-sha/yarn.lock | 247 - .../subfolder1/subfolder2/.dockerignore | 1 - .../subfolder1/subfolder2/.lagoon.yml | 4 - .../subfolder1/subfolder2/Dockerfile | 18 - .../subfolder1/subfolder2/docker-compose.yml | 23 - .../subfolder1/subfolder2/index.js | 24 - .../subfolder1/subfolder2/package.json | 12 - .../subfolder1/subfolder2/yarn.lock | 247 - tests/files/features/.dockerignore | 1 - tests/files/features/.env | 1 - tests/files/features/.env.defaults | 1 - tests/files/features/.lagoon.env.branch1 | 1 - .../files/features/.lagoon.env.slash-branch1 | 1 - .../features/.lagoon.node-env-specific.yml | 119 - tests/files/features/.lagoon.node.yml | 119 - tests/files/features/.lagoon.yml | 49 - tests/files/features/Dockerfile | 33 - tests/files/features/docker-compose.yml | 24 - tests/files/features/index.js | 24 - tests/files/features/package.json | 12 - tests/files/features/yarn.lock | 247 - tests/files/nginx/first/.lagoon.env.nginx | 1 - tests/files/nginx/first/.lagoon.yml | 21 - tests/files/nginx/first/Dockerfile | 8 - tests/files/nginx/first/Dockerfile.basic-auth | 7 - .../nginx/first/Dockerfile.basic-auth-disable | 10 - tests/files/nginx/first/app/index.html | 1 - tests/files/nginx/first/docker-compose.yml | 51 - tests/files/nginx/first/redirects-map.conf | 13 - tests/files/nginx/second/.lagoon.yml | 28 - tests/files/node6_subfolder/.lagoon.yml | 11 - .../files/node6_subfolder/docker-compose.yml | 20 - .../node6_subfolder/subfolder/.dockerignore | 1 - tests/files/node6_subfolder/subfolder/.env | 1 - .../node6_subfolder/subfolder/.env.defaults | 1 - .../subfolder/.lagoon.env.branch1 | 1 - .../subfolder/.lagoon.env.slash-branch1 | 1 - .../node6_subfolder/subfolder/Dockerfile | 36 - .../files/node6_subfolder/subfolder/index.js | 16 - .../node6_subfolder/subfolder/package.json | 12 - .../files/node6_subfolder/subfolder/yarn.lock | 247 - tests/files/node8/.dockerignore | 1 - tests/files/node8/.lagoon.yml | 11 - tests/files/node8/Dockerfile | 36 - tests/files/node8/docker-compose.yml | 20 - tests/files/node8/index.js | 19 - tests/files/node8/package.json | 12 - tests/files/node8/yarn.lock | 247 - tests/hosts | 1 - tests/tasks/api/remove.yaml | 8 - tests/tasks/git-add-commit-push.yaml | 42 - tests/tasks/git-empty-commit-push.yaml | 32 - tests/tasks/git-init.yaml | 24 - tests/tasks/git-skip-empty-commit-push.yaml | 32 - tests/tasks/pause.yaml | 3 - tests/tasks/rest/deploy-no-sha.yaml | 8 - tests/tasks/rest/deploy-sha.yaml | 8 - tests/tasks/rest/promote.yaml | 8 - tests/tasks/rest/pullrequest-deploy.yaml | 8 - tests/tasks/ssh/get-jwt-token-via-ssh.yaml | 3 - tests/tasks/ssh/ssh-command.yaml | 6 - .../webhook-bitbucket/pullrequest-closed.yaml | 10 - .../webhook-bitbucket/pullrequest-opened.yaml | 10 - .../pullrequest-updated.yaml | 10 - .../tasks/webhook-bitbucket/push-delete.yaml | 13 - .../webhook-bitbucket/push-skipdeploy.yaml | 13 - tests/tasks/webhook-bitbucket/push.yaml | 13 - .../webhook-github/pullrequest-closed.yaml | 13 - .../webhook-github/pullrequest-opened.yaml | 13 - .../pullrequest-synchronize.yaml | 13 - tests/tasks/webhook-github/push-delete.yaml | 13 - .../tasks/webhook-github/push-skipdeploy.yaml | 12 - tests/tasks/webhook-github/push.yaml | 13 - .../webhook-gitlab/pullrequest-closed.yaml | 10 - .../webhook-gitlab/pullrequest-opened.yaml | 10 - .../webhook-gitlab/pullrequest-updated.yaml | 10 - tests/tasks/webhook-gitlab/push-delete.yaml | 10 - .../tasks/webhook-gitlab/push-skipdeploy.yaml | 10 - tests/tasks/webhook-gitlab/push.yaml | 10 - tests/tests/bitbucket.yaml | 30 - tests/tests/bitbucket/branch.yaml | 96 - tests/tests/bitbucket/pullrequest.yaml | 132 - tests/tests/bitbucket/skip-deployment.yaml | 60 - tests/tests/drupal-galera.yaml | 15 - tests/tests/drupal-postgres.yaml | 35 - tests/tests/drupal.yaml | 55 - tests/tests/drupal/check-deployed.yaml | 35 - tests/tests/drupal/drupal.yaml | 66 - tests/tests/drupal/drush.yaml | 232 - tests/tests/elasticsearch.yaml | 23 - tests/tests/elasticsearch/elasticsearch.yaml | 48 - tests/tests/features.yaml | 146 - tests/tests/features/api-token.yaml | 18 - .../autogenerated-routes-disabled.yaml | 56 - tests/tests/features/cronjobs.yaml | 72 - .../features/disable-inject-git-sha.yaml | 45 - tests/tests/features/dot-env.yaml | 63 - .../tests/features/environment-templates.yaml | 45 - tests/tests/features/environment-type.yaml | 45 - .../tests/features/lagoon-api-variables.yaml | 126 - tests/tests/features/limits.yaml | 29 - tests/tests/features/multiproject.yaml | 97 - tests/tests/features/openshift-limit.yaml | 25 - tests/tests/features/promote.yaml | 79 - tests/tests/features/remote-shell.yaml | 95 - tests/tests/features/route-env-variables.yaml | 54 - tests/tests/features/subfolder.yaml | 43 - tests/tests/github.yaml | 26 - tests/tests/github/branch.yaml | 96 - tests/tests/github/pullrequest.yaml | 132 - tests/tests/github/skip-deployment.yaml | 60 - tests/tests/gitlab.yaml | 26 - tests/tests/gitlab/branch.yaml | 96 - tests/tests/gitlab/pullrequest.yaml | 129 - tests/tests/gitlab/skip-deployment.yaml | 60 - tests/tests/helpers/just-push.yaml | 23 - tests/tests/helpers/testing.yaml | 5 - tests/tests/helpers/webhook-push-delete.yaml | 8 - tests/tests/nginx.yaml | 12 - tests/tests/nginx/check-first.yaml | 188 - tests/tests/nginx/check-second.yaml | 81 - tests/tests/nginx/nginx.yaml | 65 - tests/tests/node.yaml | 23 - tests/tests/rest.yaml | 22 - tests/tests/rest/branch.yaml | 108 - tests/tests/rest/pullrequest.yaml | 126 - tests/tests/rest/push.yaml | 27 - yarn.lock | 12130 ---------- 1563 files changed, 78 insertions(+), 186948 deletions(-) delete mode 100644 .dockerignore delete mode 100644 .env.defaults delete mode 100644 .eslintignore delete mode 100644 .flowconfig delete mode 100644 .gitignore delete mode 100644 .lagoon.keycloak-secrets.yaml delete mode 100644 .lagoon.logs-db-secrets.yaml delete mode 100644 .lagoon.secrets.yaml delete mode 100644 .lagoon.yml delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 Jenkinsfile delete mode 100644 Jenkinsfile.end2end delete mode 100644 LICENSE delete mode 100644 Makefile delete mode 100644 bay/images/docker/drupal.conf delete mode 100644 bay/images/docker/my.cnf delete mode 100644 build/.gitkeep delete mode 100644 charts-values/clair/values.yaml delete mode 100644 charts-values/grafana/values.yaml delete mode 100644 charts-values/prometheus/values.yaml delete mode 100644 charts/clair/.helmignore delete mode 100644 charts/clair/Chart.yaml delete mode 100644 charts/clair/requirements.yaml delete mode 100644 charts/clair/templates/_helpers.tpl delete mode 100644 charts/clair/templates/configmap.yaml delete mode 100644 charts/clair/templates/deployment.yaml delete mode 100644 charts/clair/templates/ingress.yaml delete mode 100644 charts/clair/templates/service.yaml delete mode 100644 charts/clair/values.yaml delete mode 100755 charts/grafana-dpc/Chart.yaml delete mode 100755 charts/grafana-dpc/README.md delete mode 100755 charts/grafana-dpc/templates/NOTES.txt delete mode 100755 charts/grafana-dpc/templates/_helpers.tpl delete mode 100755 charts/grafana-dpc/templates/configmap.yaml delete mode 100755 charts/grafana-dpc/templates/dashboards-configmap.yaml delete mode 100755 charts/grafana-dpc/templates/deployment.yaml delete mode 100755 charts/grafana-dpc/templates/ingress.yaml delete mode 100644 charts/grafana-dpc/templates/job-notify.yaml delete mode 100755 charts/grafana-dpc/templates/job.yaml delete mode 100755 charts/grafana-dpc/templates/pvc.yaml delete mode 100644 charts/grafana-dpc/templates/route.yaml delete mode 100644 charts/grafana-dpc/templates/secret-oauth.yaml delete mode 100755 charts/grafana-dpc/templates/secret.yaml delete mode 100755 charts/grafana-dpc/templates/svc.yaml delete mode 100755 charts/grafana-dpc/values.yaml delete mode 100755 charts/prometheus-dpc/.helmignore delete mode 100755 charts/prometheus-dpc/Chart.yaml delete mode 100755 charts/prometheus-dpc/README.md delete mode 100755 charts/prometheus-dpc/templates/NOTES.txt delete mode 100755 charts/prometheus-dpc/templates/_helpers.tpl delete mode 100755 charts/prometheus-dpc/templates/alertmanager-clusterrolebinding.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-configmap.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-deployment.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-ingress.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-networkpolicy.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-pvc.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-service.yaml delete mode 100755 charts/prometheus-dpc/templates/alertmanager-serviceaccount.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-clusterrole.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-clusterrolebinding.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-deployment.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-networkpolicy.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-serviceaccount.yaml delete mode 100755 charts/prometheus-dpc/templates/kube-state-metrics-svc.yaml delete mode 100755 charts/prometheus-dpc/templates/node-exporter-clusterrolebinding.yaml delete mode 100755 charts/prometheus-dpc/templates/node-exporter-daemonset.yaml delete mode 100755 charts/prometheus-dpc/templates/node-exporter-service.yaml delete mode 100755 charts/prometheus-dpc/templates/node-exporter-serviceaccount.yaml delete mode 100644 charts/prometheus-dpc/templates/openshift-scc.yaml delete mode 100755 charts/prometheus-dpc/templates/pushgateway-deployment.yaml delete mode 100755 charts/prometheus-dpc/templates/pushgateway-ingress.yaml delete mode 100755 charts/prometheus-dpc/templates/pushgateway-service.yaml delete mode 100755 charts/prometheus-dpc/templates/server-clusterrole.yaml delete mode 100755 charts/prometheus-dpc/templates/server-clusterrolebinding.yaml delete mode 100755 charts/prometheus-dpc/templates/server-configmap.yaml delete mode 100755 charts/prometheus-dpc/templates/server-deployment.yaml delete mode 100644 charts/prometheus-dpc/templates/server-gluster-pvc.yaml delete mode 100755 charts/prometheus-dpc/templates/server-ingress.yaml delete mode 100755 charts/prometheus-dpc/templates/server-networkpolicy.yaml delete mode 100755 charts/prometheus-dpc/templates/server-pvc.yaml delete mode 100644 charts/prometheus-dpc/templates/server-route.yaml delete mode 100755 charts/prometheus-dpc/templates/server-service.yaml delete mode 100755 charts/prometheus-dpc/templates/server-serviceaccount.yaml delete mode 100755 charts/prometheus-dpc/values.yaml delete mode 100644 charts/trigger-quay-builds/.helmignore delete mode 100644 charts/trigger-quay-builds/Chart.yaml delete mode 100644 charts/trigger-quay-builds/templates/_helpers.tpl delete mode 100644 charts/trigger-quay-builds/templates/cronjob.yaml delete mode 100644 charts/trigger-quay-builds/templates/secret.yaml delete mode 100644 charts/trigger-quay-builds/values.yaml delete mode 100644 cli/.babelrc.js delete mode 100644 cli/.eslintignore delete mode 100644 cli/.eslintrc.js delete mode 100644 cli/.gitignore delete mode 100644 cli/.projectile delete mode 100644 cli/.yarnrc delete mode 100644 cli/10-ssh-agent.sh delete mode 100644 cli/Dockerfile delete mode 100644 cli/README.md delete mode 100755 cli/bin/lagu.js delete mode 100644 cli/jest.config.js delete mode 100644 cli/package.json delete mode 100644 cli/scripts/execute.js delete mode 100644 cli/src/__tests__/__snapshots__/e2e.test.js.snap delete mode 100644 cli/src/__tests__/e2e.test.js delete mode 100644 cli/src/__tests__/fixtures/.gitignore delete mode 100644 cli/src/__tests__/fixtures/.gitkeep delete mode 100644 cli/src/cli/answerWithOption.js delete mode 100644 cli/src/cli/promptUntilValidKeyPath.js delete mode 100644 cli/src/cli/registerCommands.js delete mode 100644 cli/src/cli/setConfigForHandlers.js delete mode 100644 cli/src/commands/__tests__/__snapshots__/customer.test.js.snap delete mode 100644 cli/src/commands/__tests__/__snapshots__/init.test.js.snap delete mode 100644 cli/src/commands/__tests__/__snapshots__/project.test.js.snap delete mode 100644 cli/src/commands/__tests__/__snapshots__/projects.test.js.snap delete mode 100644 cli/src/commands/__tests__/customer.test.js delete mode 100644 cli/src/commands/__tests__/init.test.js delete mode 100644 cli/src/commands/__tests__/project.test.js delete mode 100644 cli/src/commands/__tests__/projects.test.js delete mode 100644 cli/src/commands/customer.js delete mode 100644 cli/src/commands/environments.js delete mode 100644 cli/src/commands/init.js delete mode 100644 cli/src/commands/login.js delete mode 100644 cli/src/commands/logout.js delete mode 100644 cli/src/commands/project.js delete mode 100644 cli/src/commands/projectCommands/__tests__/__snapshots__/project-create.test.js.snap delete mode 100644 cli/src/commands/projectCommands/__tests__/project-create.test.js delete mode 100644 cli/src/commands/projectCommands/create.js delete mode 100644 cli/src/commands/projectCommands/delete.js delete mode 100644 cli/src/commands/projects.js delete mode 100644 cli/src/config/getApiConfig.js delete mode 100644 cli/src/config/getSshConfig.js delete mode 100644 cli/src/config/globalOptions.js delete mode 100644 cli/src/config/index.js delete mode 100644 cli/src/configFile/__tests__/__snapshots__/writeConfigFile.test.js.snap delete mode 100644 cli/src/configFile/__tests__/lagoon.yml delete mode 100644 cli/src/configFile/__tests__/parseConfigFile.test.js delete mode 100644 cli/src/configFile/__tests__/writeConfigFile.test.js delete mode 100644 cli/src/configFile/parseConfigFile.js delete mode 100644 cli/src/configFile/readConfigFile.js delete mode 100644 cli/src/configFile/writeConfigFile.js delete mode 100644 cli/src/formatters/__tests__/__snapshots__/csv.test.js.snap delete mode 100644 cli/src/formatters/__tests__/__snapshots__/json.test.js.snap delete mode 100644 cli/src/formatters/__tests__/__snapshots__/simple.test.js.snap delete mode 100644 cli/src/formatters/__tests__/__snapshots__/table.test.js.snap delete mode 100644 cli/src/formatters/__tests__/csv.test.js delete mode 100644 cli/src/formatters/__tests__/json.test.js delete mode 100644 cli/src/formatters/__tests__/simple.test.js delete mode 100644 cli/src/formatters/__tests__/table.test.js delete mode 100644 cli/src/formatters/csv.js delete mode 100644 cli/src/formatters/json.js delete mode 100644 cli/src/formatters/simple.js delete mode 100644 cli/src/formatters/table.js delete mode 100644 cli/src/index.js delete mode 100644 cli/src/types/Command.js delete mode 100644 cli/src/types/Config.js delete mode 100644 cli/src/types/ConfigFile.js delete mode 100644 cli/src/types/Format.js delete mode 100644 cli/src/util/__tests__/__snapshots__/format.test.js.snap delete mode 100644 cli/src/util/__tests__/__snapshots__/printErrors.test.js.snap delete mode 100644 cli/src/util/__tests__/__snapshots__/runSshCommand.test.js.snap delete mode 100644 cli/src/util/__tests__/format.test.js delete mode 100644 cli/src/util/__tests__/printErrors.test.js delete mode 100644 cli/src/util/__tests__/queryGraphQL.test.js delete mode 100644 cli/src/util/__tests__/request.test.js delete mode 100644 cli/src/util/__tests__/runSshCommand.test.js delete mode 100644 cli/src/util/format.js delete mode 100644 cli/src/util/fs.js delete mode 100644 cli/src/util/getCommandOptions.js delete mode 100644 cli/src/util/gql.js delete mode 100644 cli/src/util/printErrors.js delete mode 100644 cli/src/util/queryGraphQL.js delete mode 100644 cli/src/util/request.js delete mode 100644 cli/src/util/runSshCommand.js delete mode 100644 dashboards/examples/deployment-dashboard.json delete mode 100644 dashboards/examples/ingress.json delete mode 100644 dashboards/examples/kubernetes-capacity-planning-dashboard.json delete mode 100644 dashboards/examples/kubernetes-cluster-health-dashboard.json delete mode 100644 dashboards/examples/kubernetes-cluster-monitoring.json delete mode 100644 dashboards/examples/kubernetes-cluster-status-dashboard.json delete mode 100644 dashboards/examples/kubernetes-control-plane-status-dashboard.json delete mode 100644 dashboards/examples/kubernetes-resource-requests-dashboard.json delete mode 100644 dashboards/examples/nodes-dashboard.json delete mode 100644 dashboards/examples/nodes.json delete mode 100644 dashboards/examples/pod_metrics.json delete mode 100644 dashboards/examples/pods-dashboard.json delete mode 100644 dashboards/examples/resource-cpu-requests.json delete mode 100644 dashboards/examples/resource-memory-requests.json delete mode 100644 dashboards/examples/resource-requests.json delete mode 100644 dashboards/examples/statefulset-dashboard.json delete mode 100644 dashboards/examples/system.json delete mode 100644 dashboards/in-use/alerts.json delete mode 100644 dashboards/in-use/kubernetes-capacity-planning.json delete mode 100644 dashboards/in-use/kubernetes-control-plane-status.json delete mode 100644 dashboards/in-use/kubernetes-deployments.json delete mode 100644 dashboards/in-use/kubernetes-pods.json delete mode 100644 dashboards/in-use/kubernetes-resource-requests.json delete mode 100644 dashboards/in-use/kubernetes-statefulsets.json delete mode 100644 dashboards/in-use/mysql-cross-server-graphs.json delete mode 100644 dashboards/in-use/mysql-disk-performance.json delete mode 100644 dashboards/in-use/mysql-galera-graphs.json delete mode 100644 dashboards/in-use/mysql-innodb-metrics.json delete mode 100644 dashboards/in-use/mysql-myisam-metrics.json delete mode 100644 dashboards/in-use/mysql-overview.json delete mode 100644 dashboards/in-use/mysql-summary.json delete mode 100644 dashboards/in-use/mysql-trends.json delete mode 100644 dashboards/in-use/nodes.json delete mode 100644 dashboards/in-use/system.json delete mode 100644 dashboards/temp/Alerts Copy-1516600505131.json delete mode 100644 dashboards/temp/Cluster - Pods-1516597155979.json delete mode 100644 docker-compose.end2end.yaml delete mode 100644 docker-compose.yaml delete mode 100644 docs/SUMMARY.md delete mode 100644 docs/administering_lagoon/create-project.gql delete mode 100644 docs/administering_lagoon/graphql_api.md delete mode 100644 docs/administering_lagoon/install.md delete mode 100644 docs/administering_lagoon/openshift_requirements.md delete mode 100644 docs/clair.md delete mode 100644 docs/code_of_conduct.md delete mode 100644 docs/developing_lagoon/contributing.md delete mode 100644 docs/developing_lagoon/index.md delete mode 100644 docs/developing_lagoon/tests.md delete mode 100644 docs/helm.md create mode 100644 docs/images/SDP_Bay_product_logo_JPG.JPG create mode 100644 docs/images/SDP_Logo_VicGov_RGB.jpg create mode 100644 docs/images/Salsa.png delete mode 100644 docs/images/bb_webhook_1.png delete mode 100644 docs/images/first_deployment_slack_2nd_success.jpg delete mode 100644 docs/images/first_deployment_slack_start.jpg delete mode 100644 docs/images/first_deployment_slack_success.jpg delete mode 100644 docs/images/gh_webhook_1.png delete mode 100644 docs/images/gh_webhook_2.png delete mode 100644 docs/images/gl_webhook_1.png delete mode 100644 docs/images/grafana.png delete mode 100644 docs/images/lagoon-ui-production.png delete mode 100644 docs/images/pod_search_domains.jpg delete mode 100644 docs/images/prometheus-kube-state-metrics.png delete mode 100644 docs/images/prometheus-node-exporter.png delete mode 100644 docs/images/prometheus-server.png delete mode 100644 docs/index.md delete mode 100644 docs/links.md delete mode 100644 docs/metrics_architecture.md delete mode 100644 docs/metrics_charts.md delete mode 100644 docs/metrics_dashboards.md delete mode 100644 docs/metrics_install.md delete mode 100644 docs/quay.md delete mode 100644 docs/tests.md delete mode 100644 docs/troubleshooting.md delete mode 100644 docs/using_lagoon/backups.md delete mode 100644 docs/using_lagoon/build_deploy_process.md delete mode 100644 docs/using_lagoon/configure_webhooks.md delete mode 100644 docs/using_lagoon/docker-compose_yml.md delete mode 100644 docs/using_lagoon/docker_images/nginx.md delete mode 100644 docs/using_lagoon/docker_images/php-fpm.md delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/.dockerignore delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/.lagoon.yml delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.cli delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.nginx delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.php delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/docker-compose.yml delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/drush/aliases.drushrc.php delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/drush/drushrc.php delete mode 100755 docs/using_lagoon/drupal/drupal7-mariadb/sites/default/all.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/sites/default/development.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/sites/default/production.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal7-mariadb/sites/default/settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/.dockerignore delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/.gitignore delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/.lagoon.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.cli delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.nginx delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/docker-compose.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/drush/aliases.drushrc.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/drush/drushrc.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.services.yml delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/development.services.yml delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/development.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/example.settings.local.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/production.services.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/production.settings.php delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/.dockerignore delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/.gitignore delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/.lagoon.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.cli delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.nginx delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/docker-compose.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/drush/aliases.drushrc.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/drush/drushrc.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.services.yml delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/development.services.yml delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/development.settings.php delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/production.services.yml delete mode 100644 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/production.settings.php delete mode 100755 docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/settings.php delete mode 100644 docs/using_lagoon/drupal/drush9.md delete mode 100644 docs/using_lagoon/drupal/first_deployment.md delete mode 100644 docs/using_lagoon/drupal/lagoonize.md delete mode 100644 docs/using_lagoon/drupal/services/mariadb.md delete mode 100644 docs/using_lagoon/drupal/services/redis.md delete mode 100644 docs/using_lagoon/drupal/services/solr.md delete mode 100644 docs/using_lagoon/drupal/services/varnish.md delete mode 100644 docs/using_lagoon/environment_files.md delete mode 100644 docs/using_lagoon/environment_types.md delete mode 100644 docs/using_lagoon/first_deployment.md delete mode 100644 docs/using_lagoon/golive.md delete mode 100644 docs/using_lagoon/graphql_api.md delete mode 100644 docs/using_lagoon/index.md delete mode 100644 docs/using_lagoon/lagoon_yml.md delete mode 100644 docs/using_lagoon/local_development_environments.md delete mode 100644 docs/using_lagoon/logging.md delete mode 100644 docs/using_lagoon/migrations/amazeeio.md delete mode 100644 docs/using_lagoon/remote_shell.md delete mode 100644 docs/using_lagoon/service_types.md delete mode 100644 docs/using_lagoon/setup_project.md delete mode 100644 docs/using_lagoon/workflows.md delete mode 100644 flow-typed/custom/emit.js delete mode 100644 flow-typed/custom/execa_v0.10.x.js delete mode 100644 flow-typed/custom/express_v4.16.x.js delete mode 100644 flow-typed/custom/mocha.js delete mode 100644 flow-typed/custom/ramda_v0.x.x.js delete mode 100644 flow-typed/custom/yargs_v10.x.x.js delete mode 100644 flow-typed/npm/babel-cli_vx.x.x.js delete mode 100644 flow-typed/npm/babel-core_vx.x.x.js delete mode 100644 flow-typed/npm/babel-eslint_vx.x.x.js delete mode 100644 flow-typed/npm/babel-jest_vx.x.x.js delete mode 100644 flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js delete mode 100644 flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js delete mode 100644 flow-typed/npm/babel-plugin-transform-object-rest-spread_vx.x.x.js delete mode 100644 flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js delete mode 100644 flow-typed/npm/babel-polyfill_vx.x.x.js delete mode 100644 flow-typed/npm/babel-preset-es2015_vx.x.x.js delete mode 100644 flow-typed/npm/body-parser_v1.x.x.js delete mode 100644 flow-typed/npm/chalk_v1.x.x.js delete mode 100644 flow-typed/npm/co_vx.x.x.js delete mode 100644 flow-typed/npm/eslint-plugin-flow-vars_vx.x.x.js delete mode 100644 flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js delete mode 100644 flow-typed/npm/eslint-plugin-graphql_vx.x.x.js delete mode 100644 flow-typed/npm/eslint_vx.x.x.js delete mode 100644 flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 flow-typed/npm/inquirer_v1.x.x.js delete mode 100644 flow-typed/npm/jest_v22.x.x.js delete mode 100644 flow-typed/npm/js-yaml_vx.x.x.js delete mode 100644 flow-typed/npm/jsonwebtoken_vx.x.x.js delete mode 100644 flow-typed/npm/lint-staged_vx.x.x.js delete mode 100644 flow-typed/npm/morgan_vx.x.x.js delete mode 100644 flow-typed/npm/nano_vx.x.x.js delete mode 100644 flow-typed/npm/node-fetch_vx.x.x.js delete mode 100644 flow-typed/npm/nodemon_vx.x.x.js delete mode 100644 flow-typed/npm/pre-commit_vx.x.x.js delete mode 100644 flow-typed/npm/prettier_vx.x.x.js delete mode 100644 flow-typed/npm/rimraf_vx.x.x.js delete mode 100644 flow-typed/npm/ssh2_vx.x.x.js delete mode 100644 flow-typed/npm/sshpk_vx.x.x.js delete mode 100644 flow-typed/npm/table_vx.x.x.js delete mode 100644 flow-typed/npm/winston_vx.x.x.js delete mode 100644 helpers/annotate-pvc-backup.sh delete mode 100755 helpers/k8up-initiate.sh delete mode 100755 helpers/mariadb-galera2shared.sh delete mode 100755 helpers/mariadb-single2shared-no-nginx.sh delete mode 100755 helpers/mariadb-single2shared-wordpress.sh delete mode 100755 helpers/mariadb-single2shared.sh delete mode 100755 helpers/reclaim-pv.sh delete mode 100755 helpers/run-in-all-lagoon-projects.sh delete mode 100755 helpers/sharedmigrate.sh delete mode 100644 images/athenapdf-service/Dockerfile delete mode 100755 images/athenapdf-service/entrypoint.sh delete mode 100644 images/commons/.bashrc delete mode 100644 images/commons/Dockerfile delete mode 100755 images/commons/docker-sleep delete mode 100755 images/commons/fix-permissions delete mode 100755 images/commons/lagoon/cronjob.sh delete mode 100755 images/commons/lagoon/entrypoints.bash delete mode 100755 images/commons/lagoon/entrypoints.sh delete mode 100755 images/commons/lagoon/entrypoints/00-umask.sh delete mode 100644 images/commons/lagoon/entrypoints/10-passwd.sh delete mode 100644 images/commons/lagoon/entrypoints/50-dotenv.sh delete mode 100644 images/commons/lagoon/entrypoints/55-generate-env.sh delete mode 100644 images/commons/lagoon/entrypoints/90-cronjobs.sh delete mode 100644 images/curator/Dockerfile delete mode 100644 images/docker-host/Dockerfile delete mode 100755 images/docker-host/prune-images.sh delete mode 100755 images/docker-host/update-push-images.sh delete mode 100644 images/elasticsearch/Dockerfile delete mode 100755 images/elasticsearch/configure-es.sh delete mode 100755 images/elasticsearch/docker-entrypoint.sh delete mode 100755 images/elasticsearch/peer-finder delete mode 100644 images/kibana/Dockerfile delete mode 100644 images/logstash/Dockerfile delete mode 100644 images/mariadb-drupal/Dockerfile delete mode 100644 images/mariadb-galera-drupal/Dockerfile delete mode 100644 images/mariadb-galera/Dockerfile delete mode 100644 images/mariadb-galera/entrypoints/100-fix-data-subpath.sh delete mode 100755 images/mariadb-galera/entrypoints/100-mariadb-logging.bash delete mode 100755 images/mariadb-galera/entrypoints/150-mariadb-performance.bash delete mode 100755 images/mariadb-galera/entrypoints/200-mariadb-envplate.bash delete mode 100644 images/mariadb-galera/entrypoints/201-maxscale-envplate.bash delete mode 100755 images/mariadb-galera/entrypoints/9999-mariadb-galera-init.bash delete mode 100755 images/mariadb-galera/maxscale-start.sh delete mode 100644 images/mariadb-galera/maxscale.cnf delete mode 100644 images/mariadb-galera/maxscale.sql delete mode 100644 images/mariadb-galera/my.cnf delete mode 100755 images/mariadb-galera/mysql-backup.sh delete mode 100755 images/mariadb-galera/root/usr/bin/peer-finder delete mode 100644 images/mariadb-galera/root/usr/include/bits/wordsize.h delete mode 100755 images/mariadb-galera/root/usr/share/container-scripts/mysql/configure-galera.sh delete mode 100644 images/mariadb-galera/root/usr/share/container-scripts/mysql/galera.cnf delete mode 100755 images/mariadb-galera/root/usr/share/container-scripts/mysql/readiness-probe.sh delete mode 100644 images/mariadb/Dockerfile delete mode 100755 images/mariadb/entrypoints/100-mariadb-logging.bash delete mode 100755 images/mariadb/entrypoints/150-mariadb-performance.bash delete mode 100755 images/mariadb/entrypoints/200-mariadb-envplate.bash delete mode 100755 images/mariadb/entrypoints/9999-mariadb-init.bash delete mode 100644 images/mariadb/my.cnf delete mode 100755 images/mariadb/mysql-backup.sh delete mode 100755 images/mariadb/root/usr/share/container-scripts/mysql/readiness-probe.sh delete mode 100644 images/mongo/Dockerfile delete mode 100644 images/nginx-drupal/Dockerfile delete mode 100644 images/nginx-drupal/drupal.conf delete mode 100644 images/nginx/Dockerfile delete mode 100755 images/nginx/docker-entrypoint delete mode 100644 images/nginx/fastcgi.conf delete mode 100644 images/nginx/helpers/000_variables.conf delete mode 100644 images/nginx/helpers/010_redirects.conf delete mode 100644 images/nginx/helpers/020_basic-auth.conf delete mode 100644 images/nginx/helpers/030_ipv6-xfwdfor.conf delete mode 100644 images/nginx/helpers/100_x-robots-header-development.conf delete mode 100755 images/nginx/nginx.conf delete mode 100644 images/nginx/redirects-map.conf delete mode 100644 images/nginx/static-files.conf delete mode 100644 images/node/Dockerfile delete mode 100644 images/node/builder/Dockerfile delete mode 100644 images/oc-build-deploy-dind/Dockerfile delete mode 100644 images/oc-build-deploy-dind/README.md delete mode 100755 images/oc-build-deploy-dind/build-deploy-docker-compose.sh delete mode 100755 images/oc-build-deploy-dind/build-deploy.sh delete mode 100755 images/oc-build-deploy-dind/docker-entrypoint.sh delete mode 100644 images/oc-build-deploy-dind/openshift-templates/backup/schedule.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/cli-persistent/custom-cronjob.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/cli-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/cli/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/configmap.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/custom/custom-cronjob.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/elasticsearch-cluster/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/elasticsearch-cluster/statefulset.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/elasticsearch/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/elasticsearch/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/elasticsearch/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/kibana/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/kibana/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/kibana/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/logstash/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/logstash/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-galera/cronjobs.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-galera/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-galera/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-galera/statefulset.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-shared/servicebroker.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-single/cronjobs.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-single/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-single/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mariadb-single/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mongo-shared/servicebroker.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mongo/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mongo/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/mongo/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-persistent/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-persistent/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-persistent/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-redis-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-redis-persistent/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-redis-persistent/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php-redis-persistent/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx-php/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/nginx/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node-persistent/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node-persistent/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node-persistent/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/node/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/postgres/cronjobs.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/postgres/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/postgres/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/postgres/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/rabbitmq-cluster/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/rabbitmq-cluster/statefulset.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/rabbitmq/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/rabbitmq/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/rabbitmq/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/redis-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/redis-persistent/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/redis-persistent/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/redis/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/redis/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/route.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/solr/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/solr/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/solr/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish-persistent/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish-persistent/pvc.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish-persistent/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish-persistent/services.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish/deployment.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish/routes.yml delete mode 100644 images/oc-build-deploy-dind/openshift-templates/varnish/services.yml delete mode 100755 images/oc-build-deploy-dind/scripts/convert-crontab.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-additional-yaml.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-build.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-monitor-daemonset.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-monitor-deploy.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-monitor-statefulset.sh delete mode 100644 images/oc-build-deploy-dind/scripts/exec-openshift-create-pvc.sh delete mode 100644 images/oc-build-deploy-dind/scripts/exec-openshift-create-route.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-openshift-create-servicebroker.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-openshift-resources-with-images.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-openshift-resources.sh delete mode 100644 images/oc-build-deploy-dind/scripts/exec-openshift-tag-dockerhub.sh delete mode 100644 images/oc-build-deploy-dind/scripts/exec-openshift-tag.sh delete mode 100644 images/oc-build-deploy-dind/scripts/exec-pre-tasks-run.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-push-parallel-tug.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-push-parallel.sh delete mode 100755 images/oc-build-deploy-dind/scripts/exec-tasks-run.sh delete mode 100755 images/oc-build-deploy-dind/scripts/git-checkout-pull-merge.sh delete mode 100755 images/oc-build-deploy-dind/scripts/git-checkout-pull.sh delete mode 100755 images/oc-build-deploy-dind/tug.sh delete mode 100644 images/oc-build-deploy-dind/tug/Dockerfile delete mode 100644 images/oc-build-deploy-dind/tug/tug-build-push.sh delete mode 100644 images/oc/Dockerfile delete mode 100644 images/php/cli-drupal/Dockerfile delete mode 100644 images/php/cli-drupal/drush.yml delete mode 100644 images/php/cli-drupal/drushrc.php delete mode 100755 images/php/cli/05-ssh-key.sh delete mode 100644 images/php/cli/10-ssh-agent.sh delete mode 100644 images/php/cli/55-cli-helpers.sh delete mode 100755 images/php/cli/61-php-xdebug-cli-env.sh delete mode 100644 images/php/cli/80-shell-timeout.sh delete mode 100644 images/php/cli/90-composer-path.sh delete mode 100644 images/php/cli/Dockerfile delete mode 100644 images/php/cli/README.md delete mode 100644 images/php/cli/id_ed25519_lagoon_cli.key delete mode 100644 images/php/cli/ssh_config delete mode 100644 images/php/fpm/00-lagoon-php.ini.tpl delete mode 100644 images/php/fpm/Dockerfile delete mode 100644 images/php/fpm/README.md delete mode 100755 images/php/fpm/check_fcgi delete mode 100755 images/php/fpm/entrypoints/50-ssmtp.sh delete mode 100755 images/php/fpm/entrypoints/60-php-xdebug.sh delete mode 100755 images/php/fpm/entrypoints/70-php-config.sh delete mode 100755 images/php/fpm/entrypoints/71-php-newrelic.sh delete mode 100644 images/php/fpm/php-fpm.d/www.conf delete mode 100644 images/php/fpm/php.ini delete mode 100644 images/php/fpm/ssmtp.conf delete mode 100755 images/postgres-ckan/90-datastore-user.sh delete mode 100644 images/postgres-ckan/Dockerfile delete mode 100644 images/postgres-drupal/Dockerfile delete mode 100644 images/postgres/Dockerfile delete mode 100644 images/postgres/postgres-backup.sh delete mode 100644 images/python-ckan/Dockerfile delete mode 100644 images/python-ckandatapusher/Dockerfile delete mode 100644 images/python/80-shell-timeout.sh delete mode 100644 images/python/Dockerfile delete mode 100644 images/rabbitmq-cluster/Dockerfile delete mode 100644 images/rabbitmq-cluster/cluster-rabbit.sh delete mode 100644 images/rabbitmq-cluster/enabled_plugins delete mode 100644 images/rabbitmq-cluster/rabbitmq.conf delete mode 100644 images/rabbitmq/Dockerfile delete mode 100644 images/rabbitmq/rabbitmq_delayed_message_exchange-3.7.0.ez delete mode 100644 images/redis-persistent/Dockerfile delete mode 100644 images/redis/Dockerfile delete mode 100644 images/redis/conf/ephemeral.conf delete mode 100644 images/redis/conf/persistent.conf delete mode 100644 images/redis/conf/redis.conf delete mode 100755 images/redis/docker-entrypoint delete mode 100644 images/solr-ckan/Dockerfile delete mode 100644 images/solr-ckan/solr5.5/conf/elevate.xml delete mode 100644 images/solr-ckan/solr5.5/conf/mapping-ISOLatin1Accent.txt delete mode 100644 images/solr-ckan/solr5.5/conf/protwords.txt delete mode 100644 images/solr-ckan/solr5.5/conf/schema.xml delete mode 100644 images/solr-ckan/solr5.5/conf/solrconfig.xml delete mode 100644 images/solr-ckan/solr5.5/conf/solrconfig_extra.xml delete mode 100644 images/solr-ckan/solr5.5/conf/solrcore.properties delete mode 100644 images/solr-ckan/solr5.5/conf/stopwords.txt delete mode 100644 images/solr-ckan/solr5.5/conf/synonyms.txt delete mode 100644 images/solr-ckan/solr6.6/conf/elevate.xml delete mode 100644 images/solr-ckan/solr6.6/conf/mapping-ISOLatin1Accent.txt delete mode 100644 images/solr-ckan/solr6.6/conf/protwords.txt delete mode 100644 images/solr-ckan/solr6.6/conf/schema.xml delete mode 100644 images/solr-ckan/solr6.6/conf/solrconfig.xml delete mode 100644 images/solr-ckan/solr6.6/conf/solrconfig_spellcheck.xml delete mode 100644 images/solr-ckan/solr6.6/conf/solrcore.properties delete mode 100644 images/solr-ckan/solr6.6/conf/stopwords.txt delete mode 100644 images/solr-ckan/solr6.6/conf/synonyms.txt delete mode 100644 images/solr-drupal/Dockerfile delete mode 100644 images/solr-drupal/solr5.5/conf/elevate.xml delete mode 100644 images/solr-drupal/solr5.5/conf/mapping-ISOLatin1Accent.txt delete mode 100644 images/solr-drupal/solr5.5/conf/protwords.txt delete mode 100644 images/solr-drupal/solr5.5/conf/schema.xml delete mode 100644 images/solr-drupal/solr5.5/conf/schema_extra_fields.xml delete mode 100644 images/solr-drupal/solr5.5/conf/schema_extra_types.xml delete mode 100644 images/solr-drupal/solr5.5/conf/solrconfig.xml delete mode 100644 images/solr-drupal/solr5.5/conf/solrconfig_extra.xml delete mode 100644 images/solr-drupal/solr5.5/conf/solrcore.properties delete mode 100644 images/solr-drupal/solr5.5/conf/stopwords.txt delete mode 100644 images/solr-drupal/solr5.5/conf/synonyms.txt delete mode 100644 images/solr-drupal/solr6.6/conf/elevate.xml delete mode 100644 images/solr-drupal/solr6.6/conf/mapping-ISOLatin1Accent.txt delete mode 100644 images/solr-drupal/solr6.6/conf/protwords.txt delete mode 100644 images/solr-drupal/solr6.6/conf/schema.xml delete mode 100644 images/solr-drupal/solr6.6/conf/schema_extra_fields.xml delete mode 100644 images/solr-drupal/solr6.6/conf/schema_extra_types.xml delete mode 100644 images/solr-drupal/solr6.6/conf/schema_legacy_fields.xml delete mode 100644 images/solr-drupal/solr6.6/conf/schema_legacy_types.xml delete mode 100644 images/solr-drupal/solr6.6/conf/solrconfig.xml delete mode 100644 images/solr-drupal/solr6.6/conf/solrconfig_spellcheck.xml delete mode 100644 images/solr-drupal/solr6.6/conf/solrcore.properties delete mode 100644 images/solr-drupal/solr6.6/conf/stopwords.txt delete mode 100644 images/solr-drupal/solr6.6/conf/synonyms.txt delete mode 100644 images/solr-drupal/solr7.5/conf/elevate.xml delete mode 100644 images/solr-drupal/solr7.5/conf/mapping-ISOLatin1Accent.txt delete mode 100644 images/solr-drupal/solr7.5/conf/protwords.txt delete mode 100644 images/solr-drupal/solr7.5/conf/schema.xml delete mode 100644 images/solr-drupal/solr7.5/conf/schema_extra_fields.xml delete mode 100644 images/solr-drupal/solr7.5/conf/schema_extra_types.xml delete mode 100644 images/solr-drupal/solr7.5/conf/schema_legacy_fields.xml delete mode 100644 images/solr-drupal/solr7.5/conf/schema_legacy_types.xml delete mode 100644 images/solr-drupal/solr7.5/conf/solrconfig.xml delete mode 100644 images/solr-drupal/solr7.5/conf/solrconfig_extra.xml delete mode 100644 images/solr-drupal/solr7.5/conf/solrconfig_index.xml delete mode 100644 images/solr-drupal/solr7.5/conf/solrconfig_spellcheck.xml delete mode 100644 images/solr-drupal/solr7.5/conf/solrcore.properties delete mode 100644 images/solr-drupal/solr7.5/conf/stopwords.txt delete mode 100644 images/solr-drupal/solr7.5/conf/synonyms.txt delete mode 100755 images/solr/10-solr-port.sh delete mode 100755 images/solr/20-solr-datadir.sh delete mode 100644 images/solr/Dockerfile delete mode 100644 images/varnish-drupal/Dockerfile delete mode 100644 images/varnish-drupal/drupal.vcl delete mode 100644 images/varnish-persistent-drupal/Dockerfile delete mode 100644 images/varnish-persistent/Dockerfile delete mode 100644 images/varnish/Dockerfile delete mode 100644 images/varnish/default.vcl delete mode 100644 images/varnish/docker-entrypoint delete mode 100755 images/varnish/varnish-start.sh delete mode 100644 images/yarn-workspace-builder/Dockerfile delete mode 100644 jest.config.js delete mode 100644 lagoon-remote/.lagoon.yml delete mode 100644 lagoon-remote/README.md delete mode 100644 lagoon-remote/docker-compose.yaml delete mode 120000 lagoon-remote/docker-host delete mode 120000 lagoon-remote/logs-collector delete mode 120000 lagoon-remote/logs-forwarder delete mode 100644 lagoon-remote/logs-forwarder-logstash/.lagoon.yml delete mode 100644 lagoon-remote/logs-forwarder-logstash/Dockerfile delete mode 100644 lagoon-remote/logs-forwarder-logstash/certs/lumberjack.cert delete mode 100644 lagoon-remote/logs-forwarder-logstash/logstash.conf delete mode 100644 lagoon-remote/logs-forwarder.remote.yml delete mode 100644 local-dev/.dockerignore delete mode 100644 local-dev/api-data-watcher-pusher/Dockerfile delete mode 100755 local-dev/api-data-watcher-pusher/api-watch-push.sh delete mode 100755 local-dev/api-data-watcher-pusher/create_jwt.sh delete mode 100644 local-dev/api-data/00-clear-api-data.gql delete mode 100644 local-dev/api-data/01-populate-api-data.gql delete mode 100644 local-dev/cli_id_ed25519 delete mode 100644 local-dev/cli_id_ed25519.pub delete mode 100644 local-dev/cli_id_rsa delete mode 100644 local-dev/cli_id_rsa.pub delete mode 100644 local-dev/git/Dockerfile delete mode 100755 local-dev/git/authorized-keys.sh delete mode 100644 local-dev/git/nginx/git delete mode 100755 local-dev/git/service/fcgiwrap.sh delete mode 100755 local-dev/git/service/nginx.sh delete mode 100644 mkdocs.yml delete mode 100644 node-packages/commons/.eslintignore delete mode 100644 node-packages/commons/.eslintrc.js delete mode 100644 node-packages/commons/.projectile delete mode 100644 node-packages/commons/flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 node-packages/commons/flow-typed/npm/lokka-transport-http_vx.x.x.js delete mode 100644 node-packages/commons/flow-typed/npm/lokka_vx.x.x.js delete mode 100644 node-packages/commons/flow-typed/npm/prettier_vx.x.x.js delete mode 100644 node-packages/commons/jest.config.js delete mode 100644 node-packages/commons/package.json delete mode 100644 node-packages/commons/src/__tests__/__snapshots__/jwt.test.js.snap delete mode 100644 node-packages/commons/src/__tests__/jwt.test.js delete mode 100644 node-packages/commons/src/api.js delete mode 100644 node-packages/commons/src/gitlabApi.js delete mode 100644 node-packages/commons/src/jest-flow-transform.js delete mode 100644 node-packages/commons/src/jwt.js delete mode 100644 node-packages/commons/src/local-logging.js delete mode 100644 node-packages/commons/src/logs.js delete mode 100644 node-packages/commons/src/openshiftApi.js delete mode 100644 node-packages/commons/src/tasks.js delete mode 100644 node-packages/commons/src/types.js delete mode 100644 node-packages/eslint-config-lagoon-node/.eslintrc.js delete mode 100644 node-packages/eslint-config-lagoon-node/index.js delete mode 100644 node-packages/eslint-config-lagoon-node/package.json delete mode 100644 openshift-setup/clusterrole-daemonset-admin.yaml delete mode 100644 openshift-setup/clusterrole-openshiftbuilddeploy.yaml delete mode 100644 openshift-setup/policybinding.yaml delete mode 100644 openshift-setup/rolebinding.yaml delete mode 100644 openshift-setup/router-template.cfg delete mode 100644 openshift-setup/shared-resource-viewer.yaml delete mode 100644 package.json delete mode 100755 scripts/dev-galera.sh delete mode 100755 scripts/test-host.sh delete mode 100755 scripts/trigger_quay_builds.sh delete mode 100644 services/api-db/.projectile delete mode 100644 services/api-db/Dockerfile delete mode 100644 services/api-db/Dockerfile-galera delete mode 100644 services/api-db/Makefile delete mode 100644 services/api-db/docker-entrypoint-initdb.d/00-tables.sql delete mode 100644 services/api-db/docker-entrypoint-initdb.d/01-migrations.sql delete mode 100644 services/api-db/docker-entrypoint-initdb.d/02-views.sql delete mode 100644 services/api-db/docker-entrypoint-initdb.d/03-procedures.sql delete mode 100755 services/api-db/docker-entrypoint-initdb.d/04-generate-ssh-key-fingerprints.sh delete mode 100755 services/api-db/rerun_initdb.sh delete mode 100644 services/api/.eslintrc.js delete mode 100644 services/api/.gitignore delete mode 100644 services/api/.lagoon.app.yml delete mode 100644 services/api/.projectile delete mode 100644 services/api/Dockerfile delete mode 100644 services/api/ocaml-impl/Dockerfile delete mode 100644 services/api/ocaml-impl/Makefile delete mode 100644 services/api/ocaml-impl/README.md delete mode 100644 services/api/ocaml-impl/api-next.install delete mode 100644 services/api/ocaml-impl/api-next.opam delete mode 100644 services/api/ocaml-impl/jbuild-workspace.dev delete mode 100644 services/api/ocaml-impl/src/.merlin delete mode 100644 services/api/ocaml-impl/src/jbuild delete mode 100644 services/api/ocaml-impl/src/main.ml delete mode 100644 services/api/package.json delete mode 100644 services/api/src/apolloServer.js delete mode 100644 services/api/src/app.js delete mode 100644 services/api/src/authMiddleware.js delete mode 100644 services/api/src/authMiddleware.test.js delete mode 100644 services/api/src/clients/aws.js delete mode 100644 services/api/src/clients/esClient.js delete mode 100644 services/api/src/clients/keycloakClient.js delete mode 100644 services/api/src/clients/kibanaClient.js delete mode 100644 services/api/src/clients/pubSub.js delete mode 100644 services/api/src/clients/searchguardClient.js delete mode 100644 services/api/src/clients/sqlClient.js delete mode 100644 services/api/src/index.js delete mode 100644 services/api/src/logger.js delete mode 100644 services/api/src/resolvers.js delete mode 100644 services/api/src/resources/backup/events.js delete mode 100644 services/api/src/resources/backup/resolvers.js delete mode 100644 services/api/src/resources/backup/sql.js delete mode 100644 services/api/src/resources/customer/__snapshots__/customer.test.js.snap delete mode 100644 services/api/src/resources/customer/customer.test.js delete mode 100644 services/api/src/resources/customer/helpers.js delete mode 100644 services/api/src/resources/customer/resolvers.js delete mode 100644 services/api/src/resources/customer/searchguard.js delete mode 100644 services/api/src/resources/customer/sql.js delete mode 100644 services/api/src/resources/deployment/events.js delete mode 100644 services/api/src/resources/deployment/resolvers.js delete mode 100644 services/api/src/resources/deployment/sql.js delete mode 100644 services/api/src/resources/env-variables/resolvers.js delete mode 100644 services/api/src/resources/env-variables/sql.js delete mode 100644 services/api/src/resources/environment/__snapshots__/environment.test.js.snap delete mode 100644 services/api/src/resources/environment/environment.test.js delete mode 100644 services/api/src/resources/environment/helpers.js delete mode 100644 services/api/src/resources/environment/resolvers.js delete mode 100644 services/api/src/resources/environment/sql.js delete mode 100644 services/api/src/resources/environment/validators.js delete mode 100644 services/api/src/resources/file/resolvers.js delete mode 100644 services/api/src/resources/file/sql.js delete mode 100644 services/api/src/resources/index.js delete mode 100644 services/api/src/resources/notification/__snapshots__/notification.test.js.snap delete mode 100644 services/api/src/resources/notification/helpers.js delete mode 100644 services/api/src/resources/notification/notification.test.js delete mode 100644 services/api/src/resources/notification/resolvers.js delete mode 100644 services/api/src/resources/notification/sql.js delete mode 100644 services/api/src/resources/openshift/__snapshots__/openshift.test.js.snap delete mode 100644 services/api/src/resources/openshift/openshift.test.js delete mode 100644 services/api/src/resources/openshift/resolvers.js delete mode 100644 services/api/src/resources/openshift/sql.js delete mode 100644 services/api/src/resources/project/__snapshots__/project.test.js.snap delete mode 100644 services/api/src/resources/project/helpers.js delete mode 100644 services/api/src/resources/project/keycloak.js delete mode 100644 services/api/src/resources/project/project.test.js delete mode 100644 services/api/src/resources/project/resolvers.js delete mode 100644 services/api/src/resources/project/searchguard.js delete mode 100644 services/api/src/resources/project/sql.js delete mode 100644 services/api/src/resources/sshKey/__snapshots__/sshKey.test.js.snap delete mode 100644 services/api/src/resources/sshKey/index.js delete mode 100644 services/api/src/resources/sshKey/resolvers.js delete mode 100644 services/api/src/resources/sshKey/sql.js delete mode 100644 services/api/src/resources/sshKey/sshKey.test.js delete mode 100644 services/api/src/resources/task/events.js delete mode 100644 services/api/src/resources/task/helpers.js delete mode 100644 services/api/src/resources/task/resolvers.js delete mode 100644 services/api/src/resources/task/sql.js delete mode 100644 services/api/src/resources/user/helpers.js delete mode 100644 services/api/src/resources/user/keycloak.js delete mode 100644 services/api/src/resources/user/resolvers.js delete mode 100644 services/api/src/resources/user/sql.js delete mode 100644 services/api/src/routes/index.js delete mode 100644 services/api/src/routes/keys.js delete mode 100644 services/api/src/routes/notFound.js delete mode 100644 services/api/src/routes/status.js delete mode 100644 services/api/src/schema.js delete mode 100644 services/api/src/server.js delete mode 100644 services/api/src/typeDefs.js delete mode 100644 services/api/src/util/auth.js delete mode 100644 services/api/src/util/db.js delete mode 100644 services/api/src/util/db.test.js delete mode 100644 services/api/src/util/gql.js delete mode 100644 services/api/src/util/pickNonNil.js delete mode 100644 services/api/src/util/snakeCase.js delete mode 100644 services/api/src/util/waitAndInitKeycloak.js delete mode 100755 services/api/wait-for-mariadb.sh delete mode 100644 services/auth-server/.babelrc delete mode 100644 services/auth-server/.dockerignore delete mode 100644 services/auth-server/.eslintignore delete mode 100644 services/auth-server/.eslintrc.js delete mode 100644 services/auth-server/.gitignore delete mode 100644 services/auth-server/.lagoon.app.yml delete mode 100644 services/auth-server/.projectile delete mode 100644 services/auth-server/Dockerfile delete mode 100644 services/auth-server/README.md delete mode 100644 services/auth-server/package.json delete mode 100644 services/auth-server/src/index.js delete mode 100644 services/auth-server/src/logger.js delete mode 100644 services/auth-server/src/routes.js delete mode 100644 services/auth-server/src/util/db.js delete mode 100644 services/auth-server/src/util/routing.js delete mode 100755 services/auth-server/test/test-flow delete mode 100755 services/auth-server/test/test-lint delete mode 100644 services/auto-idler/.lagoon.yml delete mode 100644 services/auto-idler/Dockerfile delete mode 100755 services/auto-idler/create_jwt.sh delete mode 100755 services/auto-idler/idle-clis.sh delete mode 100755 services/auto-idler/idle-services.sh delete mode 100644 services/broker-single/Dockerfile delete mode 100644 services/broker/.lagoon.app.yml delete mode 100644 services/broker/Dockerfile delete mode 100644 services/docker-host/docker-host.yaml delete mode 100644 services/drush-alias/.lagoon.app.yml delete mode 100644 services/drush-alias/Dockerfile delete mode 100644 services/drush-alias/README.md delete mode 100644 services/drush-alias/docker-compose.yml delete mode 100755 services/drush-alias/nginx.conf delete mode 100644 services/drush-alias/testing/Dockerfile delete mode 100644 services/drush-alias/testing/aliases.drushrc.php delete mode 100755 services/drush-alias/testing/entrypoint.sh delete mode 100644 services/drush-alias/web/aliases.drushrc.php.stub delete mode 100644 services/drush-alias/web/index.html delete mode 100644 services/keycloak-db/Dockerfile delete mode 100644 services/keycloak-db/Dockerfile-galera delete mode 100644 services/keycloak/.lagoon.app.yml delete mode 100644 services/keycloak/Dockerfile delete mode 100755 services/keycloak/start.sh delete mode 100755 services/keycloak/wait-for-mariadb.sh delete mode 100644 services/logs-collector/.lagoon.yml delete mode 100644 services/logs-db-curator/.lagoon.app.yml delete mode 100644 services/logs-db-curator/90-generate-http-auth.sh delete mode 100644 services/logs-db-curator/Dockerfile delete mode 100644 services/logs-db-curator/actions.yml delete mode 100644 services/logs-db-curator/curator.yml delete mode 100644 services/logs-db-ui/.lagoon.yml delete mode 100644 services/logs-db-ui/Dockerfile delete mode 100644 services/logs-db-ui/README.md delete mode 100644 services/logs-db-ui/entrypoints/80-keycloak-url.bash delete mode 100644 services/logs-db-ui/entrypoints/81-logs-db-ui-url.bash delete mode 100644 services/logs-db-ui/entrypoints/90-keycloak-client-secret.bash delete mode 100644 services/logs-db/.lagoon.cluster.yml delete mode 100644 services/logs-db/.lagoon.single.yml delete mode 100644 services/logs-db/Dockerfile delete mode 100644 services/logs-db/README.md delete mode 100644 services/logs-db/entrypoints/80-keycloak-url.bash delete mode 100755 services/logs-db/es-curl delete mode 100644 services/logs-db/sgconfig/sg_config.yml delete mode 100644 services/logs-db/sgconfig/sg_internal_users.yml delete mode 100644 services/logs-db/sgconfig/sg_roles_mapping.yml delete mode 100755 services/logs-db/start.sh delete mode 100644 services/logs-forwarder/.lagoon.multi.yml delete mode 100644 services/logs-forwarder/.lagoon.single.yml delete mode 100644 services/logs-forwarder/Dockerfile delete mode 100644 services/logs-forwarder/ca_cert.pem delete mode 100644 services/logs-forwarder/ca_key.pem delete mode 100755 services/logs-forwarder/entrypoint.sh delete mode 100644 services/logs2logs-db/.lagoon.yml delete mode 100644 services/logs2logs-db/Dockerfile delete mode 100644 services/logs2logs-db/README.md delete mode 100644 services/logs2logs-db/certs/lumberjack.cert delete mode 100644 services/logs2logs-db/certs/lumberjack.key delete mode 100644 services/logs2logs-db/entrypoints/90-logstash-enable-forward-external-logstash.sh delete mode 100644 services/logs2logs-db/pipeline/debug.conf delete mode 100644 services/logs2logs-db/pipeline/lagoon-logs.conf delete mode 100644 services/logs2logs-db/pipeline/router-application-logs.conf delete mode 100644 services/logs2logs-db/pipeline/service-logs.conf delete mode 100644 services/logs2logs-db/pipelines.yml delete mode 100644 services/logs2logs-db/templates/application-logs.json delete mode 100644 services/logs2logs-db/templates/lagoon-logs.json delete mode 100644 services/logs2logs-db/templates/router-logs.json delete mode 100644 services/logs2logs-db/templates/service-logs.json delete mode 100644 services/logs2rocketchat/.babelrc delete mode 100644 services/logs2rocketchat/.flowconfig delete mode 100644 services/logs2rocketchat/.gitignore delete mode 100644 services/logs2rocketchat/.lagoon.app.yml delete mode 100644 services/logs2rocketchat/.projectile delete mode 100644 services/logs2rocketchat/Dockerfile delete mode 100644 services/logs2rocketchat/LICENSE.md delete mode 100644 services/logs2rocketchat/README.md delete mode 100644 services/logs2rocketchat/flow-typed/npm/amqp-connection-manager_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/amqplib_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-cli_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-core_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/babel-preset-es2015_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/bl_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/buffer-equal-constant-time_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/jest_v18.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/loggly-winston-bulk_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/newman_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/nodemon_vx.x.x.js delete mode 100644 services/logs2rocketchat/flow-typed/npm/winston_vx.x.x.js delete mode 100644 services/logs2rocketchat/package.json delete mode 100644 services/logs2rocketchat/src/index.js delete mode 100644 services/logs2rocketchat/src/readFromRabbitMQ.js delete mode 100644 services/logs2rocketchat/src/types.js delete mode 100644 services/logs2slack/.gitignore delete mode 100644 services/logs2slack/.lagoon.app.yml delete mode 100644 services/logs2slack/.projectile delete mode 100644 services/logs2slack/Dockerfile delete mode 100644 services/logs2slack/LICENSE.md delete mode 100644 services/logs2slack/README.md delete mode 100644 services/logs2slack/flow-typed/npm/amqp-connection-manager_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/amqplib_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-cli_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-core_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/babel-preset-es2015_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/bl_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/buffer-equal-constant-time_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/jest_v18.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/loggly-winston-bulk_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/newman_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/nodemon_vx.x.x.js delete mode 100644 services/logs2slack/flow-typed/npm/winston_vx.x.x.js delete mode 100644 services/logs2slack/package.json delete mode 100644 services/logs2slack/src/index.js delete mode 100644 services/logs2slack/src/readFromRabbitMQ.js delete mode 100644 services/logs2slack/src/types.js delete mode 100644 services/openshiftbuilddeploy/.gitignore delete mode 100644 services/openshiftbuilddeploy/.lagoon.app.yml delete mode 100644 services/openshiftbuilddeploy/.projectile delete mode 100644 services/openshiftbuilddeploy/Dockerfile delete mode 100644 services/openshiftbuilddeploy/LICENSE.md delete mode 100644 services/openshiftbuilddeploy/README.md delete mode 100644 services/openshiftbuilddeploy/package.json delete mode 100644 services/openshiftbuilddeploy/src/index.js delete mode 100644 services/openshiftbuilddeploymonitor/.gitignore delete mode 100644 services/openshiftbuilddeploymonitor/.lagoon.app.yml delete mode 100644 services/openshiftbuilddeploymonitor/.projectile delete mode 100644 services/openshiftbuilddeploymonitor/Dockerfile delete mode 100644 services/openshiftbuilddeploymonitor/LICENSE.md delete mode 100644 services/openshiftbuilddeploymonitor/README.md delete mode 100644 services/openshiftbuilddeploymonitor/package.json delete mode 100644 services/openshiftbuilddeploymonitor/src/index.js delete mode 100644 services/openshiftjobs/.gitignore delete mode 100644 services/openshiftjobs/.lagoon.app.yml delete mode 100644 services/openshiftjobs/.projectile delete mode 100644 services/openshiftjobs/Dockerfile delete mode 100644 services/openshiftjobs/LICENSE.md delete mode 100644 services/openshiftjobs/package.json delete mode 100644 services/openshiftjobs/src/index.js delete mode 100644 services/openshiftjobsmonitor/.gitignore delete mode 100644 services/openshiftjobsmonitor/.lagoon.app.yml delete mode 100644 services/openshiftjobsmonitor/.projectile delete mode 100644 services/openshiftjobsmonitor/Dockerfile delete mode 100644 services/openshiftjobsmonitor/LICENSE.md delete mode 100644 services/openshiftjobsmonitor/package.json delete mode 100644 services/openshiftjobsmonitor/src/index.js delete mode 100644 services/openshiftmisc/.gitignore delete mode 100644 services/openshiftmisc/.lagoon.app.yml delete mode 100644 services/openshiftmisc/.projectile delete mode 100644 services/openshiftmisc/Dockerfile delete mode 100644 services/openshiftmisc/LICENSE.md delete mode 100644 services/openshiftmisc/package.json delete mode 100644 services/openshiftmisc/src/handlers/resticRestore.js delete mode 100644 services/openshiftmisc/src/index.js delete mode 100644 services/openshiftremove/.gitignore delete mode 100644 services/openshiftremove/.lagoon.app.yml delete mode 100644 services/openshiftremove/.projectile delete mode 100644 services/openshiftremove/Dockerfile delete mode 100644 services/openshiftremove/LICENSE.md delete mode 100644 services/openshiftremove/README.md delete mode 100644 services/openshiftremove/package.json delete mode 100644 services/openshiftremove/src/index.js delete mode 100755 services/rest2tasks/.gitignore delete mode 100644 services/rest2tasks/.lagoon.app.yml delete mode 100644 services/rest2tasks/.projectile delete mode 100644 services/rest2tasks/Dockerfile delete mode 100755 services/rest2tasks/README.md delete mode 100755 services/rest2tasks/package.json delete mode 100755 services/rest2tasks/src/index.js delete mode 100644 services/ssh/.lagoon.app.yml delete mode 100644 services/ssh/.projectile delete mode 100644 services/ssh/Dockerfile delete mode 100644 services/ssh/README.md delete mode 100644 services/ssh/authorize.sh delete mode 100755 services/ssh/create_60_sec_jwt.sh delete mode 100755 services/ssh/docker-entrypoint.sh delete mode 100644 services/ssh/etc/libnss-mysql-root.cfg delete mode 100644 services/ssh/etc/libnss-mysql.cfg delete mode 100644 services/ssh/etc/nsswitch.conf delete mode 100644 services/ssh/etc/ssh/sshd_config delete mode 100755 services/ssh/home/command.sh delete mode 100755 services/ssh/home/rsh.sh delete mode 100755 services/ssh/home/token.sh delete mode 100644 services/ssh/libnss-mysql-1.5.tar.gz delete mode 100644 services/storage-calculator/.lagoon.yml delete mode 100644 services/storage-calculator/Dockerfile delete mode 100755 services/storage-calculator/calculate-storage.sh delete mode 100755 services/storage-calculator/create_jwt.sh delete mode 100644 services/ui/.env.defaults delete mode 100644 services/ui/.env.local delete mode 100644 services/ui/.env.schema delete mode 100644 services/ui/.gitignore delete mode 100644 services/ui/.lagoon.app.yml delete mode 100644 services/ui/Dockerfile delete mode 100644 services/ui/package.json delete mode 100644 services/ui/server.js delete mode 100644 services/ui/src/.babelrc delete mode 100644 services/ui/src/components/AddTask/components/Completed.js delete mode 100644 services/ui/src/components/AddTask/components/DrushArchiveDump.js delete mode 100644 services/ui/src/components/AddTask/components/DrushCacheClear.js delete mode 100644 services/ui/src/components/AddTask/components/DrushRsyncFiles.js delete mode 100644 services/ui/src/components/AddTask/components/DrushSqlDump.js delete mode 100644 services/ui/src/components/AddTask/components/DrushSqlSync.js delete mode 100644 services/ui/src/components/AddTask/components/Empty.js delete mode 100644 services/ui/src/components/AddTask/components/Error.js delete mode 100644 services/ui/src/components/AddTask/components/logic.js delete mode 100644 services/ui/src/components/AddTask/index.js delete mode 100644 services/ui/src/components/AddTask/logic.js delete mode 100644 services/ui/src/components/Backups/index.js delete mode 100644 services/ui/src/components/Breadcrumbs/Breadcrumb.js delete mode 100644 services/ui/src/components/Breadcrumbs/Environment.js delete mode 100644 services/ui/src/components/Breadcrumbs/Project.js delete mode 100644 services/ui/src/components/Breadcrumbs/index.js delete mode 100644 services/ui/src/components/DeleteConfirm/index.js delete mode 100644 services/ui/src/components/DeleteConfirm/logic.js delete mode 100644 services/ui/src/components/Deployment/index.js delete mode 100644 services/ui/src/components/Deployments/index.js delete mode 100644 services/ui/src/components/Environment/index.js delete mode 100644 services/ui/src/components/Environments/index.js delete mode 100644 services/ui/src/components/Footer/index.js delete mode 100644 services/ui/src/components/Header/index.js delete mode 100644 services/ui/src/components/LogViewer/index.js delete mode 100644 services/ui/src/components/Modal/index.js delete mode 100644 services/ui/src/components/NavTabs/index.js delete mode 100644 services/ui/src/components/ProjectDetailsSidebar/index.js delete mode 100644 services/ui/src/components/Projects/index.js delete mode 100644 services/ui/src/components/RestoreButton/Prepare.js delete mode 100644 services/ui/src/components/RestoreButton/index.js delete mode 100644 services/ui/src/components/Task/index.js delete mode 100644 services/ui/src/components/Tasks/index.js delete mode 100644 services/ui/src/components/link/Backups.js delete mode 100644 services/ui/src/components/link/Deployment.js delete mode 100644 services/ui/src/components/link/Deployments.js delete mode 100644 services/ui/src/components/link/Environment.js delete mode 100644 services/ui/src/components/link/Project.js delete mode 100644 services/ui/src/components/link/Task.js delete mode 100644 services/ui/src/components/link/Tasks.js delete mode 100644 services/ui/src/components/style/Box.js delete mode 100644 services/ui/src/layouts/global.js delete mode 100644 services/ui/src/layouts/main.js delete mode 100644 services/ui/src/layouts/status.js delete mode 100644 services/ui/src/lib/ApiConnection.js delete mode 100644 services/ui/src/lib/Authenticator.js delete mode 100644 services/ui/src/lib/fragment/Backup.js delete mode 100644 services/ui/src/lib/fragment/Deployment.js delete mode 100644 services/ui/src/lib/fragment/Task.js delete mode 100644 services/ui/src/lib/mutation/DeleteEnvironment.js delete mode 100644 services/ui/src/lib/polyfills.js delete mode 100644 services/ui/src/lib/query/AllProjects.js delete mode 100644 services/ui/src/lib/query/EnvironmentByOpenshiftProjectName.js delete mode 100644 services/ui/src/lib/query/EnvironmentWithBackups.js delete mode 100644 services/ui/src/lib/query/EnvironmentWithDeployment.js delete mode 100644 services/ui/src/lib/query/EnvironmentWithDeployments.js delete mode 100644 services/ui/src/lib/query/EnvironmentWithTask.js delete mode 100644 services/ui/src/lib/query/EnvironmentWithTasks.js delete mode 100644 services/ui/src/lib/query/ProjectByName.js delete mode 100644 services/ui/src/lib/subscription/Backups.js delete mode 100644 services/ui/src/lib/subscription/Deployments.js delete mode 100644 services/ui/src/lib/subscription/Tasks.js delete mode 100644 services/ui/src/lib/variables.js delete mode 100644 services/ui/src/lib/withKeycloak.js delete mode 100644 services/ui/src/lib/withLocalAuth.js delete mode 100644 services/ui/src/next.config.js delete mode 100644 services/ui/src/pages/_app.js delete mode 100644 services/ui/src/pages/_error.js delete mode 100644 services/ui/src/pages/_loading.js delete mode 100644 services/ui/src/pages/backups.js delete mode 100644 services/ui/src/pages/deployment.js delete mode 100644 services/ui/src/pages/deployments.js delete mode 100644 services/ui/src/pages/environment.js delete mode 100644 services/ui/src/pages/index.js delete mode 100644 services/ui/src/pages/project.js delete mode 100644 services/ui/src/pages/projects.js delete mode 100644 services/ui/src/pages/task.js delete mode 100644 services/ui/src/pages/tasks.js delete mode 100644 services/ui/src/static/images/backups-active.svg delete mode 100644 services/ui/src/static/images/backups.svg delete mode 100644 services/ui/src/static/images/branches.svg delete mode 100644 services/ui/src/static/images/command.svg delete mode 100644 services/ui/src/static/images/containers-active.svg delete mode 100644 services/ui/src/static/images/containers.svg delete mode 100644 services/ui/src/static/images/copy.svg delete mode 100644 services/ui/src/static/images/created.svg delete mode 100644 services/ui/src/static/images/deployments-active.svg delete mode 100644 services/ui/src/static/images/deployments.svg delete mode 100644 services/ui/src/static/images/duration.png delete mode 100644 services/ui/src/static/images/duration.svg delete mode 100644 services/ui/src/static/images/environment-branch-hover.svg delete mode 100644 services/ui/src/static/images/environment-branch.svg delete mode 100644 services/ui/src/static/images/environment-pull-request-hover.svg delete mode 100644 services/ui/src/static/images/environment-pull-request.svg delete mode 100644 services/ui/src/static/images/environments.svg delete mode 100644 services/ui/src/static/images/events-active.svg delete mode 100644 services/ui/src/static/images/events.svg delete mode 100644 services/ui/src/static/images/failed.svg delete mode 100644 services/ui/src/static/images/git-lab.svg delete mode 100644 services/ui/src/static/images/git.svg delete mode 100644 services/ui/src/static/images/header.png delete mode 100644 services/ui/src/static/images/in-progress.svg delete mode 100644 services/ui/src/static/images/last-deploy.svg delete mode 100644 services/ui/src/static/images/members.svg delete mode 100644 services/ui/src/static/images/overview-active.svg delete mode 100644 services/ui/src/static/images/overview.svg delete mode 100644 services/ui/src/static/images/pending.svg delete mode 100644 services/ui/src/static/images/profile-dropdown.svg delete mode 100644 services/ui/src/static/images/pull-request.svg delete mode 100644 services/ui/src/static/images/right-arrow.svg delete mode 100644 services/ui/src/static/images/search.png delete mode 100644 services/ui/src/static/images/service.svg delete mode 100644 services/ui/src/static/images/successful.svg delete mode 100644 services/ui/src/static/images/tasks-active.svg delete mode 100644 services/ui/src/static/images/tasks.svg delete mode 100644 services/ui/src/static/images/url.svg delete mode 100644 services/ui/src/static/normalize.css delete mode 100644 services/webhook-handler/.env delete mode 100644 services/webhook-handler/.gitignore delete mode 100644 services/webhook-handler/.lagoon.app.yml delete mode 100644 services/webhook-handler/.projectile delete mode 100644 services/webhook-handler/.vscode/settings.json delete mode 100644 services/webhook-handler/Dockerfile delete mode 100644 services/webhook-handler/LICENSE.md delete mode 100644 services/webhook-handler/README.md delete mode 100644 services/webhook-handler/docker-compose.yaml delete mode 100644 services/webhook-handler/flow-typed/npm/amqp-connection-manager_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/amqplib_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-cli_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-core_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/babel-preset-es2015_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/bl_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/buffer-equal-constant-time_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/flow-remove-types_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/jest_v18.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/loggly-winston-bulk_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/newman_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/nodemon_vx.x.x.js delete mode 100644 services/webhook-handler/flow-typed/npm/winston_vx.x.x.js delete mode 100644 services/webhook-handler/jest.config.js delete mode 100644 services/webhook-handler/newman/lagoon-webhook-handler.postman_collection.json delete mode 100644 services/webhook-handler/newman/localhost.postman_environment.json delete mode 100644 services/webhook-handler/package.json delete mode 100644 services/webhook-handler/src/__tests__/extractWebhookData-test.js delete mode 100644 services/webhook-handler/src/createReqHandler.js delete mode 100644 services/webhook-handler/src/extractWebhookData.js delete mode 100644 services/webhook-handler/src/index.js delete mode 100644 services/webhook-handler/src/jest-flow-transform.js delete mode 100644 services/webhook-handler/src/sendToLagoonWebhooks.js delete mode 100644 services/webhook-handler/src/types.js delete mode 100644 services/webhooks2tasks/.gitignore delete mode 100644 services/webhooks2tasks/.lagoon.app.yml delete mode 100644 services/webhooks2tasks/.projectile delete mode 100644 services/webhooks2tasks/.vscode/settings.json delete mode 100644 services/webhooks2tasks/Dockerfile delete mode 100644 services/webhooks2tasks/LICENSE.md delete mode 100644 services/webhooks2tasks/README.md delete mode 100644 services/webhooks2tasks/flow-typed/npm/amqp-connection-manager_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/amqplib_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-cli_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-core_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/babel-preset-es2015_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/bl_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/buffer-equal-constant-time_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/flow-bin_v0.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/jest_v18.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/loggly-winston-bulk_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/newman_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/nodemon_vx.x.x.js delete mode 100644 services/webhooks2tasks/flow-typed/npm/winston_vx.x.x.js delete mode 100644 services/webhooks2tasks/package.json delete mode 100644 services/webhooks2tasks/src/handlers/bitbucketBranchDeleted.js delete mode 100644 services/webhooks2tasks/src/handlers/bitbucketPullRequestClosed.js delete mode 100644 services/webhooks2tasks/src/handlers/bitbucketPullRequestUpdated.js delete mode 100644 services/webhooks2tasks/src/handlers/bitbucketPush.js delete mode 100644 services/webhooks2tasks/src/handlers/githubBranchDeleted.js delete mode 100644 services/webhooks2tasks/src/handlers/githubPullRequestClosed.js delete mode 100644 services/webhooks2tasks/src/handlers/githubPullRequestOpened.js delete mode 100644 services/webhooks2tasks/src/handlers/githubPullRequestSynchronize.js delete mode 100644 services/webhooks2tasks/src/handlers/githubPush.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabBranchDeleted.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabGroupCreate.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabGroupDelete.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabGroupUpdate.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabProjectCreate.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabProjectDelete.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabProjectUpdate.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabPullRequestClosed.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabPullRequestOpened.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabPullRequestUpdated.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabPush.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabSshKeyAdd.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabSshKeyRemove.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserCreate.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserCustomerAdd.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserCustomerRemove.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserDelete.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserProjectAdd.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserProjectRemove.js delete mode 100644 services/webhooks2tasks/src/handlers/gitlabUserUpdate.js delete mode 100644 services/webhooks2tasks/src/handlers/resticbackupRestoreFinished.js delete mode 100644 services/webhooks2tasks/src/handlers/resticbackupSnapshotFinished.js delete mode 100644 services/webhooks2tasks/src/handlers/resticbackupSnapshotPruned.js delete mode 100644 services/webhooks2tasks/src/index.js delete mode 100644 services/webhooks2tasks/src/processQueue.js delete mode 100644 services/webhooks2tasks/src/types.js delete mode 100644 services/webhooks2tasks/src/webhooks/backup.js delete mode 100644 services/webhooks2tasks/src/webhooks/dataSync.js delete mode 100644 services/webhooks2tasks/src/webhooks/projects.js delete mode 100644 tests/Dockerfile delete mode 100644 tests/ansible.cfg delete mode 100644 tests/checks/check-api-request.yaml delete mode 100644 tests/checks/check-branch-sha.yaml delete mode 100644 tests/checks/check-deployed.yaml delete mode 100644 tests/checks/check-dot-env.yaml delete mode 100644 tests/checks/check-json-content.yaml delete mode 100644 tests/checks/check-pullrequest.yaml delete mode 100644 tests/checks/check-url-content-absent.yaml delete mode 100644 tests/checks/check-url-content-basic-auth-host.yaml delete mode 100644 tests/checks/check-url-content-basic-auth.yaml delete mode 100644 tests/checks/check-url-content-host.yaml delete mode 100644 tests/checks/check-url-content.yaml delete mode 100644 tests/checks/check-url-header-absent.yaml delete mode 100644 tests/checks/check-url-header.yaml delete mode 100644 tests/checks/check-url-redirect-host.yaml delete mode 100644 tests/checks/check-url-redirect.yaml delete mode 100644 tests/checks/check-url-returncode-host.yaml delete mode 100644 tests/checks/check-url-returncode.yaml delete mode 100755 tests/entrypoint.sh delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.postgres delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php5.6/Dockerfile.varnish delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.postgres delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php7.0/Dockerfile.varnish delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.postgres delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php7.1/Dockerfile.varnish delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php7.2-galera/Dockerfile.varnish delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.postgres delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php7.2/Dockerfile.varnish delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.builder delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.mariadb delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.nginx delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.php delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.postgres delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.redis delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.solr delete mode 100644 tests/files/drupal8-dockerfiles/php7.3/Dockerfile.varnish delete mode 100644 tests/files/drupal8-mariadb/.dockerignore delete mode 100644 tests/files/drupal8-mariadb/.gitignore delete mode 100644 tests/files/drupal8-mariadb/.lagoon.yml delete mode 100644 tests/files/drupal8-mariadb/LICENSE delete mode 100644 tests/files/drupal8-mariadb/README.md delete mode 100644 tests/files/drupal8-mariadb/composer.json delete mode 100644 tests/files/drupal8-mariadb/composer.lock delete mode 100644 tests/files/drupal8-mariadb/config/sync/.gitkeep delete mode 100644 tests/files/drupal8-mariadb/docker-compose.yml delete mode 100644 tests/files/drupal8-mariadb/drush/README.md delete mode 100644 tests/files/drupal8-mariadb/drush/aliases.drushrc.php delete mode 100644 tests/files/drupal8-mariadb/drush/drushrc.php delete mode 100644 tests/files/drupal8-mariadb/drush/policy.drush.inc delete mode 100644 tests/files/drupal8-mariadb/scripts/composer/ScriptHandler.php delete mode 100644 tests/files/drupal8-mariadb/web/.csslintrc delete mode 100644 tests/files/drupal8-mariadb/web/.editorconfig delete mode 100644 tests/files/drupal8-mariadb/web/.eslintignore delete mode 100644 tests/files/drupal8-mariadb/web/.eslintrc.json delete mode 100644 tests/files/drupal8-mariadb/web/.gitattributes delete mode 100644 tests/files/drupal8-mariadb/web/.htaccess delete mode 100644 tests/files/drupal8-mariadb/web/autoload.php delete mode 100644 tests/files/drupal8-mariadb/web/index.php delete mode 100644 tests/files/drupal8-mariadb/web/modules/.gitkeep delete mode 100644 tests/files/drupal8-mariadb/web/profiles/.gitkeep delete mode 100644 tests/files/drupal8-mariadb/web/robots.txt delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/all.services.yml delete mode 100755 tests/files/drupal8-mariadb/web/sites/default/all.settings.php delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/default.services.yml delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/default.settings.php delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/development.services.yml delete mode 100755 tests/files/drupal8-mariadb/web/sites/default/development.settings.php delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/example.settings.local.php delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/production.services.yml delete mode 100644 tests/files/drupal8-mariadb/web/sites/default/production.settings.php delete mode 100755 tests/files/drupal8-mariadb/web/sites/default/settings.php delete mode 100644 tests/files/drupal8-mariadb/web/sites/example.sites.php delete mode 100644 tests/files/drupal8-mariadb/web/themes/.gitkeep delete mode 100644 tests/files/drupal8-mariadb/web/update.php delete mode 100644 tests/files/drupal8-mariadb/web/web.config delete mode 100644 tests/files/drupal8-postgres/.dockerignore delete mode 100644 tests/files/drupal8-postgres/.gitignore delete mode 100644 tests/files/drupal8-postgres/.lagoon.yml delete mode 100644 tests/files/drupal8-postgres/LICENSE delete mode 100644 tests/files/drupal8-postgres/README.md delete mode 100644 tests/files/drupal8-postgres/composer.json delete mode 100644 tests/files/drupal8-postgres/composer.lock delete mode 100644 tests/files/drupal8-postgres/config/sync/.gitkeep delete mode 100644 tests/files/drupal8-postgres/docker-compose.yml delete mode 100644 tests/files/drupal8-postgres/drush/README.md delete mode 100644 tests/files/drupal8-postgres/drush/aliases.drushrc.php delete mode 100644 tests/files/drupal8-postgres/drush/drushrc.php delete mode 100644 tests/files/drupal8-postgres/drush/policy.drush.inc delete mode 100644 tests/files/drupal8-postgres/scripts/composer/ScriptHandler.php delete mode 100644 tests/files/drupal8-postgres/web/.csslintrc delete mode 100644 tests/files/drupal8-postgres/web/.editorconfig delete mode 100644 tests/files/drupal8-postgres/web/.eslintignore delete mode 100644 tests/files/drupal8-postgres/web/.eslintrc.json delete mode 100644 tests/files/drupal8-postgres/web/.gitattributes delete mode 100644 tests/files/drupal8-postgres/web/.htaccess delete mode 100644 tests/files/drupal8-postgres/web/autoload.php delete mode 100644 tests/files/drupal8-postgres/web/index.php delete mode 100644 tests/files/drupal8-postgres/web/modules/.gitkeep delete mode 100644 tests/files/drupal8-postgres/web/profiles/.gitkeep delete mode 100644 tests/files/drupal8-postgres/web/robots.txt delete mode 100644 tests/files/drupal8-postgres/web/sites/default/all.services.yml delete mode 100755 tests/files/drupal8-postgres/web/sites/default/all.settings.php delete mode 100644 tests/files/drupal8-postgres/web/sites/default/default.services.yml delete mode 100644 tests/files/drupal8-postgres/web/sites/default/default.settings.php delete mode 100644 tests/files/drupal8-postgres/web/sites/default/development.services.yml delete mode 100755 tests/files/drupal8-postgres/web/sites/default/development.settings.php delete mode 100644 tests/files/drupal8-postgres/web/sites/default/example.settings.local.php delete mode 100644 tests/files/drupal8-postgres/web/sites/default/production.services.yml delete mode 100644 tests/files/drupal8-postgres/web/sites/default/production.settings.php delete mode 100755 tests/files/drupal8-postgres/web/sites/default/settings.php delete mode 100644 tests/files/drupal8-postgres/web/sites/example.sites.php delete mode 100644 tests/files/drupal8-postgres/web/themes/.gitkeep delete mode 100644 tests/files/drupal8-postgres/web/update.php delete mode 100644 tests/files/drupal8-postgres/web/web.config delete mode 100644 tests/files/elasticsearch-cluster/.lagoon.yml delete mode 100644 tests/files/elasticsearch-cluster/Dockerfile.elasticsearch delete mode 100644 tests/files/elasticsearch-cluster/Dockerfile.nginx delete mode 100644 tests/files/elasticsearch-cluster/app.conf delete mode 100644 tests/files/elasticsearch-cluster/docker-compose.yml delete mode 100644 tests/files/elasticsearch/.lagoon.yml delete mode 100644 tests/files/elasticsearch/Dockerfile.elasticsearch delete mode 100644 tests/files/elasticsearch/Dockerfile.nginx delete mode 100644 tests/files/elasticsearch/app.conf delete mode 100644 tests/files/elasticsearch/docker-compose.yml delete mode 100644 tests/files/features-autogenerated-routes-disabled/.dockerignore delete mode 100644 tests/files/features-autogenerated-routes-disabled/.lagoon.yml delete mode 100644 tests/files/features-autogenerated-routes-disabled/Dockerfile delete mode 100644 tests/files/features-autogenerated-routes-disabled/docker-compose.yml delete mode 100644 tests/files/features-autogenerated-routes-disabled/index.js delete mode 100644 tests/files/features-autogenerated-routes-disabled/package.json delete mode 100644 tests/files/features-autogenerated-routes-disabled/yarn.lock delete mode 100644 tests/files/features-disable-inject-git-sha/.dockerignore delete mode 100644 tests/files/features-disable-inject-git-sha/.lagoon.yml delete mode 100644 tests/files/features-disable-inject-git-sha/Dockerfile delete mode 100644 tests/files/features-disable-inject-git-sha/docker-compose.yml delete mode 100644 tests/files/features-disable-inject-git-sha/index.js delete mode 100644 tests/files/features-disable-inject-git-sha/package.json delete mode 100644 tests/files/features-disable-inject-git-sha/yarn.lock delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/.dockerignore delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/.lagoon.yml delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/Dockerfile delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/docker-compose.yml delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/index.js delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/package.json delete mode 100644 tests/files/features-subfolder/subfolder1/subfolder2/yarn.lock delete mode 100644 tests/files/features/.dockerignore delete mode 100644 tests/files/features/.env delete mode 100644 tests/files/features/.env.defaults delete mode 100644 tests/files/features/.lagoon.env.branch1 delete mode 100644 tests/files/features/.lagoon.env.slash-branch1 delete mode 100644 tests/files/features/.lagoon.node-env-specific.yml delete mode 100644 tests/files/features/.lagoon.node.yml delete mode 100644 tests/files/features/.lagoon.yml delete mode 100644 tests/files/features/Dockerfile delete mode 100644 tests/files/features/docker-compose.yml delete mode 100644 tests/files/features/index.js delete mode 100644 tests/files/features/package.json delete mode 100644 tests/files/features/yarn.lock delete mode 100644 tests/files/nginx/first/.lagoon.env.nginx delete mode 100644 tests/files/nginx/first/.lagoon.yml delete mode 100644 tests/files/nginx/first/Dockerfile delete mode 100644 tests/files/nginx/first/Dockerfile.basic-auth delete mode 100644 tests/files/nginx/first/Dockerfile.basic-auth-disable delete mode 100644 tests/files/nginx/first/app/index.html delete mode 100644 tests/files/nginx/first/docker-compose.yml delete mode 100644 tests/files/nginx/first/redirects-map.conf delete mode 100644 tests/files/nginx/second/.lagoon.yml delete mode 100644 tests/files/node6_subfolder/.lagoon.yml delete mode 100644 tests/files/node6_subfolder/docker-compose.yml delete mode 100644 tests/files/node6_subfolder/subfolder/.dockerignore delete mode 100644 tests/files/node6_subfolder/subfolder/.env delete mode 100644 tests/files/node6_subfolder/subfolder/.env.defaults delete mode 100644 tests/files/node6_subfolder/subfolder/.lagoon.env.branch1 delete mode 100644 tests/files/node6_subfolder/subfolder/.lagoon.env.slash-branch1 delete mode 100644 tests/files/node6_subfolder/subfolder/Dockerfile delete mode 100644 tests/files/node6_subfolder/subfolder/index.js delete mode 100644 tests/files/node6_subfolder/subfolder/package.json delete mode 100644 tests/files/node6_subfolder/subfolder/yarn.lock delete mode 100644 tests/files/node8/.dockerignore delete mode 100644 tests/files/node8/.lagoon.yml delete mode 100644 tests/files/node8/Dockerfile delete mode 100644 tests/files/node8/docker-compose.yml delete mode 100644 tests/files/node8/index.js delete mode 100644 tests/files/node8/package.json delete mode 100644 tests/files/node8/yarn.lock delete mode 100644 tests/hosts delete mode 100644 tests/tasks/api/remove.yaml delete mode 100644 tests/tasks/git-add-commit-push.yaml delete mode 100644 tests/tasks/git-empty-commit-push.yaml delete mode 100644 tests/tasks/git-init.yaml delete mode 100644 tests/tasks/git-skip-empty-commit-push.yaml delete mode 100644 tests/tasks/pause.yaml delete mode 100644 tests/tasks/rest/deploy-no-sha.yaml delete mode 100644 tests/tasks/rest/deploy-sha.yaml delete mode 100644 tests/tasks/rest/promote.yaml delete mode 100644 tests/tasks/rest/pullrequest-deploy.yaml delete mode 100644 tests/tasks/ssh/get-jwt-token-via-ssh.yaml delete mode 100644 tests/tasks/ssh/ssh-command.yaml delete mode 100644 tests/tasks/webhook-bitbucket/pullrequest-closed.yaml delete mode 100644 tests/tasks/webhook-bitbucket/pullrequest-opened.yaml delete mode 100644 tests/tasks/webhook-bitbucket/pullrequest-updated.yaml delete mode 100644 tests/tasks/webhook-bitbucket/push-delete.yaml delete mode 100644 tests/tasks/webhook-bitbucket/push-skipdeploy.yaml delete mode 100644 tests/tasks/webhook-bitbucket/push.yaml delete mode 100644 tests/tasks/webhook-github/pullrequest-closed.yaml delete mode 100644 tests/tasks/webhook-github/pullrequest-opened.yaml delete mode 100644 tests/tasks/webhook-github/pullrequest-synchronize.yaml delete mode 100644 tests/tasks/webhook-github/push-delete.yaml delete mode 100644 tests/tasks/webhook-github/push-skipdeploy.yaml delete mode 100644 tests/tasks/webhook-github/push.yaml delete mode 100644 tests/tasks/webhook-gitlab/pullrequest-closed.yaml delete mode 100644 tests/tasks/webhook-gitlab/pullrequest-opened.yaml delete mode 100644 tests/tasks/webhook-gitlab/pullrequest-updated.yaml delete mode 100644 tests/tasks/webhook-gitlab/push-delete.yaml delete mode 100644 tests/tasks/webhook-gitlab/push-skipdeploy.yaml delete mode 100644 tests/tasks/webhook-gitlab/push.yaml delete mode 100644 tests/tests/bitbucket.yaml delete mode 100644 tests/tests/bitbucket/branch.yaml delete mode 100644 tests/tests/bitbucket/pullrequest.yaml delete mode 100644 tests/tests/bitbucket/skip-deployment.yaml delete mode 100644 tests/tests/drupal-galera.yaml delete mode 100644 tests/tests/drupal-postgres.yaml delete mode 100644 tests/tests/drupal.yaml delete mode 100644 tests/tests/drupal/check-deployed.yaml delete mode 100644 tests/tests/drupal/drupal.yaml delete mode 100644 tests/tests/drupal/drush.yaml delete mode 100644 tests/tests/elasticsearch.yaml delete mode 100644 tests/tests/elasticsearch/elasticsearch.yaml delete mode 100644 tests/tests/features.yaml delete mode 100644 tests/tests/features/api-token.yaml delete mode 100644 tests/tests/features/autogenerated-routes-disabled.yaml delete mode 100644 tests/tests/features/cronjobs.yaml delete mode 100644 tests/tests/features/disable-inject-git-sha.yaml delete mode 100644 tests/tests/features/dot-env.yaml delete mode 100644 tests/tests/features/environment-templates.yaml delete mode 100644 tests/tests/features/environment-type.yaml delete mode 100644 tests/tests/features/lagoon-api-variables.yaml delete mode 100644 tests/tests/features/limits.yaml delete mode 100644 tests/tests/features/multiproject.yaml delete mode 100644 tests/tests/features/openshift-limit.yaml delete mode 100644 tests/tests/features/promote.yaml delete mode 100644 tests/tests/features/remote-shell.yaml delete mode 100644 tests/tests/features/route-env-variables.yaml delete mode 100644 tests/tests/features/subfolder.yaml delete mode 100644 tests/tests/github.yaml delete mode 100644 tests/tests/github/branch.yaml delete mode 100644 tests/tests/github/pullrequest.yaml delete mode 100644 tests/tests/github/skip-deployment.yaml delete mode 100644 tests/tests/gitlab.yaml delete mode 100644 tests/tests/gitlab/branch.yaml delete mode 100644 tests/tests/gitlab/pullrequest.yaml delete mode 100644 tests/tests/gitlab/skip-deployment.yaml delete mode 100644 tests/tests/helpers/just-push.yaml delete mode 100644 tests/tests/helpers/testing.yaml delete mode 100644 tests/tests/helpers/webhook-push-delete.yaml delete mode 100644 tests/tests/nginx.yaml delete mode 100644 tests/tests/nginx/check-first.yaml delete mode 100644 tests/tests/nginx/check-second.yaml delete mode 100644 tests/tests/nginx/nginx.yaml delete mode 100644 tests/tests/node.yaml delete mode 100644 tests/tests/rest.yaml delete mode 100644 tests/tests/rest/branch.yaml delete mode 100644 tests/tests/rest/pullrequest.yaml delete mode 100644 tests/tests/rest/push.yaml delete mode 100644 yarn.lock diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index d29fb9023..000000000 --- a/.dockerignore +++ /dev/null @@ -1,7 +0,0 @@ -**/node_modules -.dockerignore -.git -tests -.cache -Makefile -local-dev/minishift \ No newline at end of file diff --git a/.env.defaults b/.env.defaults deleted file mode 100644 index 140b99bc7..000000000 --- a/.env.defaults +++ /dev/null @@ -1,7 +0,0 @@ -# These credential information is no secret, it's just for easy -# development. Don't use these values for production deployment! -JWTSECRET=super-secret-string -JWTAUDIENCE=api.dev -AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX -AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxx -AWS_BUCKET=aws-bucket diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index bf6cd742c..000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -**/flow-typed/ -**/node_modules/ \ No newline at end of file diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index 68120521c..000000000 --- a/.flowconfig +++ /dev/null @@ -1,22 +0,0 @@ -# Keep this file in the root of the project to enable proper module resolution. -# https://twitter.com/ryyppy/status/917287307912339456 -# https://github.com/thejameskyle/__flow-with-yarn-workspaces -# -[ignore] -.*node_modules/fbjs.* -.*node_modules/node-uuid.* -/images/ -/tests/ -# Too many errors for now (as of June 2018). Enable again when errors fixed. -/services/logs2slack/ -/services/openshiftbuilddeploy/ -/services/openshiftbuilddeploymonitor/ -/services/openshiftremove/ -/services/rest2tasks/ -/services/webhook-handler/ -/services/webhooks2tasks/ - -[include] - -[libs] -flow-typed \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d9b4bff51..000000000 --- a/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -node-helpers -virtual-machine -deploytest -.DS_Store -.idea -*.retry -startVagrant.sh -local-dev/oc -minishift -**/v8-* -node_modules/ -build/* -!build/.gitkeep -openshift -!services/api/src/resources/openshift -.loopback -secrets -docs/_build -*~ -yarn-debug.log* -yarn-error.log* diff --git a/.lagoon.keycloak-secrets.yaml b/.lagoon.keycloak-secrets.yaml deleted file mode 100644 index b9255de95..000000000 --- a/.lagoon.keycloak-secrets.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: v1 -kind: Template -metadata: - creationTimestamp: null - name: lagoon-secret-environment-template -parameters: - - name: KEYCLOAK_LAGOON_ADMIN_PASSWORD - description: super admin password of keycloak - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: KEYCLOAK_ADMIN_PASSWORD - description: admin user password of keycloak - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: SAFE_BRANCH - description: Which branch this belongs to, special chars replaced with dashes - required: true - - name: SAFE_PROJECT - description: Which project this belongs to, special chars replaced with dashes - required: true - - name: BRANCH - description: Which branch this belongs to, original value - required: true - - name: PROJECT - description: Which project this belongs to, original value - required: true - - name: LAGOON_GIT_SHA - description: git hash sha of the current deployment - required: true - - name: OPENSHIFT_PROJECT - description: Name of the Project that this service is in - required: true -objects: -- kind: Secret - apiVersion: v1 - metadata: - name: keycloak-lagoon-admin-password - stringData: - KEYCLOAK_LAGOON_ADMIN_PASSWORD: ${KEYCLOAK_LAGOON_ADMIN_PASSWORD} -- kind: Secret - apiVersion: v1 - metadata: - name: keycloak-admin-password - stringData: - KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD} \ No newline at end of file diff --git a/.lagoon.logs-db-secrets.yaml b/.lagoon.logs-db-secrets.yaml deleted file mode 100644 index ce9c3a2a3..000000000 --- a/.lagoon.logs-db-secrets.yaml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: v1 -kind: Template -metadata: - creationTimestamp: null - name: lagoon-secret-environment-template -parameters: - - name: LOGSDB_ADMIN_PASSWORD - description: admin password of logs-db - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: LOGSDB_KIBANASERVER_PASSWORD - description: kibana password of logs-db - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: SAFE_BRANCH - description: Which branch this belongs to, special chars replaced with dashes - required: true - - name: SAFE_PROJECT - description: Which project this belongs to, special chars replaced with dashes - required: true - - name: BRANCH - description: Which branch this belongs to, original value - required: true - - name: PROJECT - description: Which project this belongs to, original value - required: true - - name: LAGOON_GIT_SHA - description: git hash sha of the current deployment - required: true - - name: OPENSHIFT_PROJECT - description: Name of the Project that this service is in - required: true -objects: -- kind: Secret - apiVersion: v1 - metadata: - name: logs-db-admin-password - stringData: - LOGSDB_ADMIN_PASSWORD: ${LOGSDB_ADMIN_PASSWORD} -- kind: Secret - apiVersion: v1 - metadata: - name: logs-db-kibanaserver-password - stringData: - LOGSDB_KIBANASERVER_PASSWORD: ${LOGSDB_KIBANASERVER_PASSWORD} \ No newline at end of file diff --git a/.lagoon.secrets.yaml b/.lagoon.secrets.yaml deleted file mode 100644 index 10e8dac65..000000000 --- a/.lagoon.secrets.yaml +++ /dev/null @@ -1,81 +0,0 @@ -apiVersion: v1 -kind: Template -metadata: - creationTimestamp: null - name: lagoon-secret-environment-template -parameters: - - name: JWTSECRET - description: JSON Web Token generation secret - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: RABBITMQ_PASSWORD - description: Password to connect to rabbitmq to - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: LOGSTASH_USERNAME - description: Username to for incoming logstash http connections - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: LOGSTASH_PASSWORD - description: Password to for incoming logstash http connections - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: SEARCHGUARD_COOKIE_PASSWORD - description: Password to for searchguard cookies - generate: expression - from: "[a-zA-Z0-9]{32}" - - name: SAFE_BRANCH - description: Which branch this belongs to, special chars replaced with dashes - required: true - - name: SAFE_PROJECT - description: Which project this belongs to, special chars replaced with dashes - required: true - - name: BRANCH - description: Which branch this belongs to, original value - required: true - - name: PROJECT - description: Which project this belongs to, original value - required: true - - name: LAGOON_GIT_SHA - description: git hash sha of the current deployment - required: true - - name: OPENSHIFT_PROJECT - description: Name of the Project that this service is in - required: true -objects: -- kind: Secret - apiVersion: v1 - metadata: - name: jwtsecret - stringData: - JWTSECRET: ${JWTSECRET} -- kind: Secret - apiVersion: v1 - metadata: - name: rabbitmq-password - stringData: - RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD} -- kind: Secret - apiVersion: v1 - metadata: - name: rabbitmq-username - stringData: - RABBITMQ_USERNAME: lagoon -- kind: Secret - apiVersion: v1 - metadata: - name: logstash-username - stringData: - LOGSTASH_USERNAME: ${LOGSTASH_USERNAME} -- kind: Secret - apiVersion: v1 - metadata: - name: logstash-password - stringData: - LOGSTASH_PASSWORD: ${LOGSTASH_PASSWORD} -- kind: Secret - apiVersion: v1 - metadata: - name: searchguard-cookie-password - stringData: - SEARCHGUARD_COOKIE_PASSWORD: ${SEARCHGUARD_COOKIE_PASSWORD} diff --git a/.lagoon.yml b/.lagoon.yml deleted file mode 100644 index 2f7fd2c71..000000000 --- a/.lagoon.yml +++ /dev/null @@ -1,60 +0,0 @@ -docker-compose-yaml: docker-compose.yaml - -additional-yaml: - secrets: - path: .lagoon.secrets.yaml - command: create - ignore_error: true - - logs-db-secrets: - path: .lagoon.logs-db-secrets.yaml - command: create - ignore_error: true - - keycloak-secrets: - path: .lagoon.keycloak-secrets.yaml - command: create - ignore_error: true - -tasks: -# pre-rollout: -# - run: -# name: 'disable shard allocation on elasticsearch and run synced flush' # see https://www.elastic.co/guide/en/elasticsearch/reference/current/restart-upgrade.html -# command: | -# es-curl PUT _cluster/settings -d '{"persistent":{"cluster.routing.allocation.enable":"none"}}' -# es-curl POST _flush/synced -# service: logs-db - - post-rollout: - - run: - name: update database schema - command: /rerun_initdb.sh - service: api-db - - run: - name: 'enable shard allocation on elasticsearch' - command: es-curl PUT _cluster/settings -d '{"persistent":{"cluster.routing.allocation.enable":null}}' - service: logs-db - -environments: - master: - types: - logs-db: elasticsearch-cluster - templates: - logs-db: services/logs-db/.lagoon.cluster.yml - logs-forwarder: services/logs-forwarder/.lagoon.multi.yml - rollouts: - logs-db: statefulset - logs-forwarder: statefulset - cronjobs: - - name: idle-clis - schedule: '*/15 * * * *' - command: /idle-clis.sh - service: auto-idler - - name: idle-services - schedule: '*/30 * * * *' - command: /idle-services.sh - service: auto-idler - - name: curator - schedule: '01 0 * * * ' - command: /usr/bin/curator --config /curator/curator.yml /curator/actions.yml - service: logs-db-curator diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 82eac61f5..000000000 --- a/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -package.json -**/flow-typed/** \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 544138be4..000000000 --- a/.prettierrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "singleQuote": true -} diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 9b112b141..000000000 --- a/Jenkinsfile +++ /dev/null @@ -1,134 +0,0 @@ -node { - - // MINISHIFT_HOME will be used by minishift to define where to put the docker machines - // We want them all in a unified place to be able to know how many machines there are, etc. So we put them in the - // Jenkins HOME Folder - env.MINISHIFT_HOME = "${env.JENKINS_HOME}/.minishift" - - withEnv(['AWS_BUCKET=jobs.amazeeio.services', 'AWS_DEFAULT_REGION=us-east-2']) { - withCredentials([usernamePassword(credentialsId: 'aws-s3-lagoon', usernameVariable: 'AWS_ACCESS_KEY_ID', passwordVariable: 'AWS_SECRET_ACCESS_KEY')]) { - try { - env.CI_BUILD_TAG = env.BUILD_TAG.replaceAll('%2f','').replaceAll("[^A-Za-z0-9]+", "").toLowerCase() - env.SAFEBRANCH_NAME = env.BRANCH_NAME.replaceAll('%2f','-').replaceAll("[^A-Za-z0-9]+", "-").toLowerCase() - - deleteDir() - - stage ('Checkout') { - def checkout = checkout scm - env.GIT_COMMIT = checkout["GIT_COMMIT"] - sh "git fetch --tags" - } - - stage ('build images') { - sh "make build" - } - - stage ('push images to amazeeiolagoon/*') { - withCredentials([string(credentialsId: 'amazeeiojenkins-dockerhub-password', variable: 'PASSWORD')]) { - sh 'docker login -u amazeeiojenkins -p $PASSWORD' - sh "make publish-amazeeiolagoon-baseimages publish-amazeeiolagoon-serviceimages BRANCH_NAME=${SAFEBRANCH_NAME} -j4" - } - } - - lock('minishift') { - notifySlack() - - try { - parallel ( - 'start services': { - stage ('start services') { - sh "make kill" - sh "make up" - sh "sleep 60" - } - }, - 'start minishift': { - stage ('start minishift') { - sh 'make minishift MINISHIFT_CPUS=8 MINISHIFT_MEMORY=12GB MINISHIFT_DISK_SIZE=50GB' - } - } - ) - } catch (e) { - echo "Something went wrong, trying to cleanup" - cleanup() - throw e - } - - parallel ( - '_tests': { - stage ('run tests') { - try { - sh "make push-minishift" - sh "make tests -j2" - } catch (e) { - echo "Something went wrong, trying to cleanup" - cleanup() - throw e - } - cleanup() - } - }, - 'logs': { - stage ('all') { - sh "make logs" - } - }, - ) - } - - if (env.TAG_NAME) { - stage ('publish-amazeeio') { - withCredentials([string(credentialsId: 'amazeeiojenkins-dockerhub-password', variable: 'PASSWORD')]) { - sh 'docker login -u amazeeiojenkins -p $PASSWORD' - sh "make publish-amazeeio-baseimages -j4" - } - } - } - - if (env.BRANCH_NAME == 'master') { - stage ('save-images-s3') { - sh "make s3-save -j8" - } - } - - } catch (e) { - currentBuild.result = 'FAILURE' - throw e - } finally { - notifySlack(currentBuild.result) - } - } - } - -} - -def cleanup() { - try { - sh "make down" - sh "make minishift/clean" - sh "make clean" - } catch (error) { - echo "cleanup failed, ignoring this." - } -} - -def notifySlack(String buildStatus = 'STARTED') { - // Build status of null means success. - buildStatus = buildStatus ?: 'SUCCESS' - - def color - - if (buildStatus == 'STARTED') { - color = '#68A1D1' - } else if (buildStatus == 'SUCCESS') { - color = '#BDFFC3' - } else if (buildStatus == 'UNSTABLE') { - color = '#FFFE89' - } else { - color = '#FF9FA1' - } - - def msg = "${buildStatus}: `${env.JOB_NAME}` #${env.BUILD_NUMBER}:\n${env.BUILD_URL}" - - slackSend(color: color, message: msg) -} diff --git a/Jenkinsfile.end2end b/Jenkinsfile.end2end deleted file mode 100644 index 1a612a4aa..000000000 --- a/Jenkinsfile.end2end +++ /dev/null @@ -1,21 +0,0 @@ -node { - - stage ('Checkout') { - deleteDir() - checkout scm - } - - ansiColor('xterm') { - stage ('run test') { - try { - sh "make end2end-tests -j1" - } catch (e) { - echo "Something went wrong, trying to cleanup" - sh "make end2end-tests/clean" - throw e - } - sh "make end2end-tests/clean" - } - } - -} \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8dada3eda..000000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/Makefile b/Makefile deleted file mode 100644 index 074e4b8f6..000000000 --- a/Makefile +++ /dev/null @@ -1,812 +0,0 @@ -SHELL := /bin/bash -# amazee.io lagoon Makefile The main purpose of this Makefile is to provide easier handling of -# building images and running tests It understands the relation of the different images (like -# nginx-drupal is based on nginx) and builds them in the correct order Also it knows which -# services in docker-compose.yml are depending on which base images or maybe even other service -# images -# -# The main commands are: - -# make build/ -# Builds an individual image and all of it's needed parents. Run `make build-list` to get a list of -# all buildable images. Make will keep track of each build image with creating an empty file with -# the name of the image in the folder `build`. If you want to force a rebuild of the image, either -# remove that file or run `make clean` - -# make build -# builds all images in the correct order. Uses existing images for layer caching, define via `TAG` -# which branch should be used - -# make tests/ -# Runs individual tests. In a nutshell it does: -# 1. Builds all needed images for the test -# 2. Starts needed Lagoon services for the test via docker-compose up -# 3. Executes the test -# -# Run `make tests-list` to see a list of all tests. - -# make tests -# Runs all tests together. Can be executed with `-j2` for two parallel running tests - -# make up -# Starts all Lagoon Services at once, usefull for local development or just to start all of them. - -# make logs -# Shows logs of Lagoon Services (aka docker-compose logs -f) - -# make minishift -# Some tests need a full openshift running in order to test deployments and such. This can be -# started via openshift. It will: -# 1. Download minishift cli -# 2. Start an OpenShift Cluster -# 3. Configure OpenShift cluster to our needs - -# make minishift/stop -# Removes an OpenShift Cluster - -# make minishift/clean -# Removes all openshift related things: OpenShift itself and the minishift cli - -####### -####### Default Variables -####### - -# Parameter for all `docker build` commands, can be overwritten by passing `DOCKER_BUILD_PARAMS=` via the `-e` option -DOCKER_BUILD_PARAMS := --quiet - -# Version and Hash of the OpenShift cli that should be downloaded -MINISHIFT_VERSION := 1.16.1 - -MINISHIFT_CPUS := 6 -MINISHIFT_MEMORY := 2GB -MINISHIFT_DISK_SIZE := 30GB - -# On CI systems like jenkins we need a way to run multiple testings at the same time. We expect the -# CI systems to define an Environment variable CI_BUILD_TAG which uniquely identifies each build. -# If it's not set we assume that we are running local and just call it lagoon. -CI_BUILD_TAG ?= lagoon - -ARCH := $(shell uname) -LAGOON_VERSION := $(shell git describe --tags --exact-match 2>/dev/null || echo development) -# Name of the Branch we are currently in -BRANCH_NAME := - -####### -####### Functions -####### - -# Builds a docker image. Expects as arguments: name of the image, location of Dockerfile, path of -# Docker Build Context -docker_build = docker build $(DOCKER_BUILD_PARAMS) --build-arg LAGOON_VERSION=$(LAGOON_VERSION) --build-arg IMAGE_REPO=$(CI_BUILD_TAG) -t $(CI_BUILD_TAG)/$(1) -f $(2) $(3) - -# Build a Python docker image. Expects as arguments: -# 1. Python version -# 2. Location of Dockerfile -# 3. Path of Docker Build context -docker_build_python = docker build $(DOCKER_BUILD_PARAMS) --build-arg LAGOON_VERSION=$(LAGOON_VERSION) --build-arg IMAGE_REPO=$(CI_BUILD_TAG) --build-arg PYTHON_VERSION=$(1) -t $(CI_BUILD_TAG)/python:$(2) -f $(3) $(4) - -# Build a PHP docker image. Expects as arguments: -# 1. PHP version -# 2. PHP version and type of image (ie 7.0-fpm, 7.0-cli etc) -# 3. Location of Dockerfile -# 4. Path of Docker Build Context -docker_build_php = docker build $(DOCKER_BUILD_PARAMS) --build-arg LAGOON_VERSION=$(LAGOON_VERSION) --build-arg IMAGE_REPO=$(CI_BUILD_TAG) --build-arg PHP_VERSION=$(1) -t $(CI_BUILD_TAG)/php:$(2) -f $(3) $(4) - -docker_build_node = docker build $(DOCKER_BUILD_PARAMS) --build-arg LAGOON_VERSION=$(LAGOON_VERSION) --build-arg IMAGE_REPO=$(CI_BUILD_TAG) --build-arg NODE_VERSION=$(1) -t $(CI_BUILD_TAG)/node:$(2) -f $(3) $(4) - -docker_build_solr = docker build $(DOCKER_BUILD_PARAMS) --build-arg LAGOON_VERSION=$(LAGOON_VERSION) --build-arg IMAGE_REPO=$(CI_BUILD_TAG) --build-arg SOLR_MAJ_MIN_VERSION=$(1) -t $(CI_BUILD_TAG)/solr:$(2) -f $(3) $(4) - -# Tags an image with the `amazeeio` repository and pushes it -docker_publish_amazeeio = docker tag $(CI_BUILD_TAG)/$(1) amazeeio/$(2) && docker push amazeeio/$(2) | cat - -# Tags an image with the `amazeeiolagoon` repository and pushes it -docker_publish_amazeeiolagoon = docker tag $(CI_BUILD_TAG)/$(1) amazeeiolagoon/$(2) && docker push amazeeiolagoon/$(2) | cat - - -####### -####### Base Images -####### -####### Base Images are the base for all other images and are also published for clients to use during local development - -images := oc \ - mariadb \ - mariadb-drupal \ - mariadb-galera \ - mariadb-galera-drupal \ - postgres \ - postgres-ckan \ - postgres-drupal \ - oc-build-deploy-dind \ - commons \ - nginx \ - nginx-drupal \ - varnish \ - varnish-drupal \ - varnish-persistent \ - varnish-persistent-drupal \ - redis \ - redis-persistent \ - rabbitmq \ - rabbitmq-cluster \ - mongo \ - elasticsearch \ - kibana \ - logstash \ - athenapdf-service \ - curator \ - docker-host - -# base-images is a variable that will be constantly filled with all base image there are -base-images += $(images) -s3-images += $(images) - -# List with all images prefixed with `build/`. Which are the commands to actually build images -build-images = $(foreach image,$(images),build/$(image)) - -# Define the make recepie for all base images -$(build-images): -# Generate variable image without the prefix `build/` - $(eval image = $(subst build/,,$@)) -# Call the docker build - $(call docker_build,$(image),images/$(image)/Dockerfile,images/$(image)) -# Touch an empty file which make itself is using to understand when the image has been last build - touch $@ - -# Define dependencies of Base Images so that make can build them in the right order. There are two -# types of Dependencies -# 1. Parent Images, like `build/centos7-node6` is based on `build/centos7` and need to be rebuild -# if the parent has been built -# 2. Dockerfiles of the Images itself, will cause make to rebuild the images if something has -# changed on the Dockerfiles -build/mariadb: build/commons images/mariadb/Dockerfile -build/mariadb-drupal: build/mariadb images/mariadb-drupal/Dockerfile -build/mariadb-galera: build/commons images/mariadb-galera/Dockerfile -build/mariadb-galera-drupal: build/mariadb-galera images/mariadb-galera-drupal/Dockerfile -build/postgres: build/commons images/postgres/Dockerfile -build/postgres-ckan: build/postgres images/postgres-ckan/Dockerfile -build/postgres-drupal: build/postgres images/postgres-drupal/Dockerfile -build/commons: images/commons/Dockerfile -build/nginx: build/commons images/nginx/Dockerfile -build/nginx-drupal: build/nginx images/nginx-drupal/Dockerfile -build/varnish: build/commons images/varnish/Dockerfile -build/varnish-drupal: build/varnish images/varnish-drupal/Dockerfile -build/varnish-persistent: build/commons images/varnish/Dockerfile -build/varnish-persistent-drupal: build/varnish images/varnish-drupal/Dockerfile -build/redis: build/commons images/redis/Dockerfile -build/redis-persistent: build/redis images/redis-persistent/Dockerfile -build/rabbitmq: build/commons images/rabbitmq/Dockerfile -build/rabbitmq-cluster: build/rabbitmq images/rabbitmq-cluster/Dockerfile -build/mongo: build/commons images/mongo/Dockerfile -build/elasticsearch: build/commons images/elasticsearch/Dockerfile -build/logstash: build/commons images/logstash/Dockerfile -build/kibana: build/commons images/kibana/Dockerfile -build/docker-host: build/commons images/docker-host/Dockerfile -build/oc: build/commons images/oc/Dockerfile -build/curator: build/commons images/curator/Dockerfile -build/oc-build-deploy-dind: build/oc images/oc-build-deploy-dind -build/athenapdf-service: images/athenapdf-service/Dockerfile - - -####### -####### Python Images -####### -####### Python Images are alpine linux based Python images. - -pythonimages := python__2.7 \ - python__3.7 \ - python__2.7-ckan \ - python__2.7-ckandatapusher - -build-pythonimages = $(foreach image,$(pythonimages),build/$(image)) - -# Define the make recepie for all base images -$(build-pythonimages): build/commons - $(eval clean = $(subst build/python__,,$@)) - $(eval version = $(word 1,$(subst -, ,$(clean)))) - $(eval type = $(word 2,$(subst -, ,$(clean)))) -# this fills variables only if $type is existing, if not they are just empty - $(eval type_dash = $(if $(type),-$(type))) -# Call the docker build - $(call docker_build_python,$(version),$(version)$(type_dash),images/python$(type_dash)/Dockerfile,images/python$(type_dash)) -# Touch an empty file which make itself is using to understand when the image has been last build - touch $@ - -base-images-with-versions += $(pythonimages) -s3-images += python - -build/python__2.7 build/python__3.7: images/commons -build/python__2.7-ckan: build/python__2.7 -build/python__2.7-ckandatapusher: build/python__2.7 - - -####### -####### PHP Images -####### -####### PHP Images are alpine linux based PHP images. - -phpimages := php__5.6-fpm \ - php__7.0-fpm \ - php__7.1-fpm \ - php__7.2-fpm \ - php__7.3-fpm \ - php__5.6-cli \ - php__7.0-cli \ - php__7.1-cli \ - php__7.2-cli \ - php__7.3-cli \ - php__5.6-cli-drupal \ - php__7.0-cli-drupal \ - php__7.1-cli-drupal \ - php__7.2-cli-drupal \ - php__7.3-cli-drupal - - -build-phpimages = $(foreach image,$(phpimages),build/$(image)) - -# Define the make recepie for all base images -$(build-phpimages): build/commons - $(eval clean = $(subst build/php__,,$@)) - $(eval version = $(word 1,$(subst -, ,$(clean)))) - $(eval type = $(word 2,$(subst -, ,$(clean)))) - $(eval subtype = $(word 3,$(subst -, ,$(clean)))) -# this fills variables only if $type is existing, if not they are just empty - $(eval type_dash = $(if $(type),-$(type))) - $(eval type_slash = $(if $(type),/$(type))) -# if there is a subtype, add it. If not, just keep what we already had - $(eval type_dash = $(if $(subtype),-$(type)-$(subtype),$(type_dash))) - $(eval type_slash = $(if $(subtype),/$(type)-$(subtype),$(type_slash))) -# Call the docker build - $(call docker_build_php,$(version),$(version)$(type_dash),images/php$(type_slash)/Dockerfile,images/php$(type_slash)) -# Touch an empty file which make itself is using to understand when the image has been last build - touch $@ - -base-images-with-versions += $(phpimages) -s3-images += php - -build/php__5.6-fpm build/php__7.0-fpm build/php__7.1-fpm build/php__7.2-fpm build/php__7.3-fpm: images/commons -build/php__5.6-cli: build/php__5.6-fpm -build/php__7.0-cli: build/php__7.0-fpm -build/php__7.1-cli: build/php__7.1-fpm -build/php__7.2-cli: build/php__7.2-fpm -build/php__7.3-cli: build/php__7.3-fpm -build/php__5.6-cli-drupal: build/php__5.6-cli -build/php__7.0-cli-drupal: build/php__7.0-cli -build/php__7.1-cli-drupal: build/php__7.1-cli -build/php__7.2-cli-drupal: build/php__7.2-cli -build/php__7.3-cli-drupal: build/php__7.3-cli - -####### -####### Solr Images -####### -####### Solr Images are alpine linux based Solr images. - -solrimages := solr__5.5 \ - solr__6.6 \ - solr__7.5 \ - solr__5.5-drupal \ - solr__6.6-drupal \ - solr__7.5-drupal \ - solr__5.5-ckan \ - solr__6.6-ckan - - -build-solrimages = $(foreach image,$(solrimages),build/$(image)) - -# Define the make recepie for all base images -$(build-solrimages): build/commons - $(eval clean = $(subst build/solr__,,$@)) - $(eval version = $(word 1,$(subst -, ,$(clean)))) - $(eval type = $(word 2,$(subst -, ,$(clean)))) -# this fills variables only if $type is existing, if not they are just empty - $(eval type_dash = $(if $(type),-$(type))) -# Call the docker build - $(call docker_build_solr,$(version),$(version)$(type_dash),images/solr$(type_dash)/Dockerfile,images/solr$(type_dash)) -# Touch an empty file which make itself is using to understand when the image has been last build - touch $@ - -base-images-with-versions += $(solrimages) -s3-images += solr - -build/solr__5.5 build/solr__6.6 build/solr__7.5: images/commons -build/solr__5.5-drupal: build/solr__5.5 -build/solr__6.6-drupal: build/solr__6.6 -build/solr__7.5-drupal: build/solr__7.5 -build/solr__5.5-ckan: build/solr__5.5 -build/solr__6.6-ckan: build/solr__6.6 - -####### -####### Node Images -####### -####### Node Images are alpine linux based Node images. - -nodeimages := node__10 \ - node__9 \ - node__8 \ - node__6 \ - node__10-builder \ - node__9-builder \ - node__8-builder \ - node__6-builder - -build-nodeimages = $(foreach image,$(nodeimages),build/$(image)) - -# Define the make recepie for all base images -$(build-nodeimages): build/commons - $(eval clean = $(subst build/node__,,$@)) - $(eval version = $(word 1,$(subst -, ,$(clean)))) - $(eval type = $(word 2,$(subst -, ,$(clean)))) -# this fills variables only if $type is existing, if not they are just empty - $(eval type_dash = $(if $(type),-$(type))) - $(eval type_slash = $(if $(type),/$(type))) -# Call the docker build - $(call docker_build_node,$(version),$(version)$(type_dash),images/node$(type_slash)/Dockerfile,images/node$(type_slash)) -# Touch an empty file which make itself is using to understand when the image has been last build - touch $@ - -base-images-with-versions += $(nodeimages) -s3-images += node - -build/node__9 build/node__8 build/node__6: images/commons images/node/Dockerfile -build/node__10-builder: build/node__10 images/node/builder/Dockerfile -build/node__9-builder: build/node__9 images/node/builder/Dockerfile -build/node__8-builder: build/node__8 images/node/builder/Dockerfile -build/node__6-builder: build/node__6 images/node/builder/Dockerfile - -####### -####### Service Images -####### -####### Services Images are the Docker Images used to run the Lagoon Microservices, these images -####### will be expected by docker-compose to exist. - -# Yarn Workspace Image which builds the Yarn Workspace within a single image. This image will be -# used by all microservices based on Node.js to not build similar node packages again -build-images += yarn-workspace-builder -build/yarn-workspace-builder: build/node__8-builder images/yarn-workspace-builder/Dockerfile - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),images/$(image)/Dockerfile,.) - touch $@ - -# Variables of service images we manage and build -services := api \ - auth-server \ - logs2slack \ - logs2rocketchat \ - openshiftbuilddeploy \ - openshiftbuilddeploymonitor \ - openshiftjobs \ - openshiftjobsmonitor \ - openshiftmisc \ - openshiftremove \ - rest2tasks \ - webhook-handler \ - webhooks2tasks \ - broker \ - broker-single \ - logs-forwarder \ - logs-db \ - logs-db-ui \ - logs-db-curator \ - logs2logs-db \ - auto-idler \ - storage-calculator \ - api-db \ - drush-alias \ - keycloak \ - keycloak-db \ - ui - -services-galera := api-db-galera \ - keycloak-db-galera - -service-images += $(services) $(services-galera) - -build-services = $(foreach image,$(services),build/$(image)) - -# Recepie for all building service-images -$(build-services): - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),services/$(image)/Dockerfile,services/$(image)) - touch $@ - -build-services-galera = $(foreach image,$(services-galera),build/$(image)) - -$(build-services-galera): - $(eval image = $(subst build/,,$@)) - $(eval service = $(subst -galera,,$(image))) - $(call docker_build,$(image),services/$(service)/Dockerfile-galera,services/$(service)) - touch $@ - -# Dependencies of Service Images -build/auth-server build/logs2slack build/logs2rocketchat build/openshiftbuilddeploy build/openshiftbuilddeploymonitor build/openshiftjobs build/openshiftjobsmonitor build/openshiftmisc build/openshiftremove build/rest2tasks build/webhook-handler build/webhooks2tasks build/api build/cli build/ui: build/yarn-workspace-builder -build/logs2logs-db: build/logstash -build/logs-db: build/elasticsearch -build/logs-db-ui: build/kibana -build/logs-db-curator: build/curator -build/auto-idler: build/oc -build/storage-calculator: build/oc -build/api-db build/keycloak-db: build/mariadb -build/api-db-galera build/keycloak-db-galera: build/mariadb-galera -build/broker: build/rabbitmq-cluster -build/broker-single: build/rabbitmq - -# Auth SSH needs the context of the root folder, so we have it individually -build/ssh: build/commons - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),services/$(image)/Dockerfile,.) - touch $@ -service-images += ssh - -# Images for local helpers that exist in another folder than the service images -localdevimages := local-git \ - local-api-data-watcher-pusher -service-images += $(localdevimages) -build-localdevimages = $(foreach image,$(localdevimages),build/$(image)) - -$(build-localdevimages): - $(eval folder = $(subst build/local-,,$@)) - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),local-dev/$(folder)/Dockerfile,local-dev/$(folder)) - touch $@ - -# Images for local helpers that exist in another folder than the service images -cliimages := cli -service-images += $(cliimages) - -build/cli: build/ssh cli/Dockerfile - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),cli/Dockerfile,cli) - touch $@ - -# Image with ansible test -build/tests: - $(eval image = $(subst build/,,$@)) - $(call docker_build,$(image),$(image)/Dockerfile,$(image)) - touch $@ -service-images += tests - -s3-images += $(service-images) - -####### -####### Commands -####### -####### List of commands in our Makefile - -# Builds all Images -.PHONY: build -build: $(foreach image,$(base-images) $(base-images-with-versions) $(service-images),build/$(image)) -# Outputs a list of all Images we manage -.PHONY: build-list -build-list: - @for number in $(foreach image,$(build-images),build/$(image)); do \ - echo $$number ; \ - done - -# Define list of all tests -all-tests-list:= features \ - node \ - drupal \ - drupal-postgres \ - drupal-galera \ - github \ - gitlab \ - bitbucket \ - rest \ - nginx \ - elasticsearch -all-tests = $(foreach image,$(all-tests-list),tests/$(image)) - -# Run all tests -.PHONY: tests -tests: $(all-tests) - -# List of tests existing -.PHONY: tests-list -tests-list: - @for number in $(all-tests); do \ - echo $$number ; \ - done -#### Definition of tests - -# Define a list of which Lagoon Services are needed for running any deployment testing -deployment-test-services-main = broker openshiftremove openshiftbuilddeploy openshiftbuilddeploymonitor logs2slack logs2rocketchat api ssh auth-server local-git local-api-data-watcher-pusher tests - -# All Tests that use REST endpoints -rest-tests = rest node features nginx elasticsearch -run-rest-tests = $(foreach image,$(rest-tests),tests/$(image)) -# List of Lagoon Services needed for REST endpoint testing -deployment-test-services-rest = $(deployment-test-services-main) rest2tasks -.PHONY: $(run-rest-tests) -$(run-rest-tests): minishift build/node__6-builder build/node__8-builder build/oc-build-deploy-dind $(foreach image,$(deployment-test-services-rest),build/$(image)) push-minishift - $(eval testname = $(subst tests/,,$@)) - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d $(deployment-test-services-rest) - IMAGE_REPO=$(CI_BUILD_TAG) docker exec -i $$(docker-compose -p $(CI_BUILD_TAG) ps -q tests) ansible-playbook /ansible/tests/$(testname).yaml $(testparameter) - -tests/drupal tests/drupal-postgres tests/drupal-galera: minishift build/varnish-drupal build/solr__5.5-drupal build/nginx-drupal build/redis build/php__5.6-cli-drupal build/php__7.0-cli-drupal build/php__7.1-cli-drupal build/php__7.2-cli-drupal build/php__7.3-cli-drupal build/api-db build/postgres-drupal build/mariadb-drupal build/postgres-ckan build/oc-build-deploy-dind $(foreach image,$(deployment-test-services-rest),build/$(image)) build/drush-alias push-minishift - $(eval testname = $(subst tests/,,$@)) - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d $(deployment-test-services-rest) drush-alias - IMAGE_REPO=$(CI_BUILD_TAG) docker exec -i $$(docker-compose -p $(CI_BUILD_TAG) ps -q tests) ansible-playbook /ansible/tests/$(testname).yaml $(testparameter) - -# All tests that use Webhook endpoints -webhook-tests = github gitlab bitbucket -run-webhook-tests = $(foreach image,$(webhook-tests),tests/$(image)) -# List of Lagoon Services needed for webhook endpoint testing -deployment-test-services-webhooks = $(deployment-test-services-main) webhook-handler webhooks2tasks -.PHONY: $(run-webhook-tests) -$(run-webhook-tests): openshift build/node__6-builder build/node__8-builder build/oc-build-deploy-dind $(foreach image,$(deployment-test-services-webhooks),build/$(image)) push-minishift - $(eval testname = $(subst tests/,,$@)) - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d $(deployment-test-services-webhooks) - IMAGE_REPO=$(CI_BUILD_TAG) docker exec -i $$(docker-compose -p $(CI_BUILD_TAG) ps -q tests) ansible-playbook /ansible/tests/$(testname).yaml $(testparameter) - - -end2end-all-tests = $(foreach image,$(all-tests-list),end2end-tests/$(image)) - -.PHONY: end2end-tests -end2end-tests: $(end2end-all-tests) - -.PHONY: start-end2end-ansible -start-end2end-ansible: build/tests - docker-compose -f docker-compose.yaml -f docker-compose.end2end.yaml -p end2end up -d tests - -$(end2end-all-tests): start-end2end-ansible - $(eval testname = $(subst end2end-tests/,,$@)) - docker exec -i $$(docker-compose -f docker-compose.yaml -f docker-compose.end2end.yaml -p end2end ps -q tests) ansible-playbook /ansible/tests/$(testname).yaml - -end2end-tests/clean: - docker-compose -f docker-compose.yaml -f docker-compose.end2end.yaml -p end2end down -v - -# push command of our base images into minishift -push-minishift-images = $(foreach image,$(base-images) $(base-images-with-versions),[push-minishift]-$(image)) -# tag and push all images -.PHONY: push-minishift -push-minishift: minishift/login-docker-registry $(push-minishift-images) -# tag and push of each image -.PHONY: $(push-minishift-images) -$(push-minishift-images): - $(eval image = $(subst [push-minishift]-,,$@)) - $(eval image = $(subst __,:,$(image))) - $(info pushing $(image) to minishift registry) - if docker inspect $(CI_BUILD_TAG)/$(image) > /dev/null 2>&1; then \ - docker tag $(CI_BUILD_TAG)/$(image) $$(cat minishift):30000/lagoon/$(image) && \ - docker push $$(cat minishift):30000/lagoon/$(image) | cat; \ - fi - -push-docker-host-image: build/docker-host minishift/login-docker-registry - docker tag $(CI_BUILD_TAG)/docker-host $$(cat minishift):30000/lagoon/docker-host - docker push $$(cat minishift):30000/lagoon/docker-host | cat - -lagoon-kickstart: $(foreach image,$(deployment-test-services-rest),build/$(image)) - IMAGE_REPO=$(CI_BUILD_TAG) CI=false docker-compose -p $(CI_BUILD_TAG) up -d $(deployment-test-services-rest) - sleep 30 - curl -X POST http://localhost:5555/deploy -H 'content-type: application/json' -d '{ "projectName": "lagoon", "branchName": "master" }' - make logs - -# Publish command to amazeeio docker hub, this should probably only be done during a master deployments -publish-amazeeio-baseimages = $(foreach image,$(base-images),[publish-amazeeio-baseimages]-$(image)) -publish-amazeeio-baseimages-with-versions = $(foreach image,$(base-images-with-versions),[publish-amazeeio-baseimages-with-versions]-$(image)) -# tag and push all images -.PHONY: publish-amazeeio-baseimages -publish-amazeeio-baseimages: $(publish-amazeeio-baseimages) $(publish-amazeeio-baseimages-with-versions) - - -# tag and push of each image -.PHONY: $(publish-amazeeio-baseimages) -$(publish-amazeeio-baseimages): -# Calling docker_publish for image, but remove the prefix '[publish-amazeeio-baseimages]-' first - $(eval image = $(subst [publish-amazeeio-baseimages]-,,$@)) -# Publish images as :latest - $(call docker_publish_amazeeio,$(image),$(image):latest) -# Publish images with version tag - $(call docker_publish_amazeeio,$(image),$(image):$(LAGOON_VERSION)) - - -# tag and push of base image with version -.PHONY: $(publish-amazeeio-baseimages-with-versions) -$(publish-amazeeio-baseimages-with-versions): -# Calling docker_publish for image, but remove the prefix '[publish-amazeeio-baseimages-with-versions]-' first - $(eval image = $(subst [publish-amazeeio-baseimages-with-versions]-,,$@)) -# The underline is a placeholder for a colon, replace that - $(eval image = $(subst __,:,$(image))) -# These images already use a tag to differentiate between different versions of the service itself (like node:9 and node:10) -# Therefore they don't have any latest tag - $(call docker_publish_amazeeio,$(image),$(image)) -# We add the Lagoon Version just as a dash - $(call docker_publish_amazeeio,$(image),$(image)-$(LAGOON_VERSION)) - - - -# Publish command to amazeeio docker hub, this should probably only be done during a master deployments -publish-amazeeiolagoon-baseimages = $(foreach image,$(base-images),[publish-amazeeiolagoon-baseimages]-$(image)) -publish-amazeeiolagoon-baseimages-with-versions = $(foreach image,$(base-images-with-versions),[publish-amazeeiolagoon-baseimages-with-versions]-$(image)) -# tag and push all images -.PHONY: publish-amazeeiolagoon-baseimages -publish-amazeeiolagoon-baseimages: $(publish-amazeeiolagoon-baseimages) $(publish-amazeeiolagoon-baseimages-with-versions) - - -# tag and push of each image -.PHONY: $(publish-amazeeiolagoon-baseimages) -$(publish-amazeeiolagoon-baseimages): -# Calling docker_publish for image, but remove the prefix '[publish-amazeeiolagoon-baseimages]-' first - $(eval image = $(subst [publish-amazeeiolagoon-baseimages]-,,$@)) -# Publish images with version tag - $(call docker_publish_amazeeiolagoon,$(image),$(image):$(BRANCH_NAME)) - - -# tag and push of base image with version -.PHONY: $(publish-amazeeiolagoon-baseimages-with-versions) -$(publish-amazeeiolagoon-baseimages-with-versions): -# Calling docker_publish for image, but remove the prefix '[publish-amazeeiolagoon-baseimages-with-versions]-' first - $(eval image = $(subst [publish-amazeeiolagoon-baseimages-with-versions]-,,$@)) -# The underline is a placeholder for a colon, replace that - $(eval image = $(subst __,:,$(image))) -# We add the Lagoon Version just as a dash - $(call docker_publish_amazeeiolagoon,$(image),$(image)-$(BRANCH_NAME)) - - -# Publish command to amazeeio docker hub, this should probably only be done during a master deployments -publish-amazeeiolagoon-serviceimages = $(foreach image,$(service-images),[publish-amazeeiolagoon-serviceimages]-$(image)) -# tag and push all images -.PHONY: publish-amazeeiolagoon-serviceimages -publish-amazeeiolagoon-serviceimages: $(publish-amazeeiolagoon-serviceimages) - - -# tag and push of each image -.PHONY: $(publish-amazeeiolagoon-serviceimages) -$(publish-amazeeiolagoon-serviceimages): -# Calling docker_publish for image, but remove the prefix '[publish-amazeeiolagoon-serviceimages]-' first - $(eval image = $(subst [publish-amazeeiolagoon-serviceimages]-,,$@)) -# Publish images with version tag - $(call docker_publish_amazeeiolagoon,$(image),$(image):$(BRANCH_NAME)) - - -s3-save = $(foreach image,$(s3-images),[s3-save]-$(image)) -# save all images to s3 -.PHONY: s3-save -s3-save: $(s3-save) -# tag and push of each image -.PHONY: $(s3-save) -$(s3-save): -# remove the prefix '[s3-save]-' first - $(eval image = $(subst [s3-save]-,,$@)) - $(eval image = $(subst __,:,$(image))) - docker save $(CI_BUILD_TAG)/$(image) $$(docker history -q $(CI_BUILD_TAG)/$(image) | grep -v missing) | gzip -9 | aws s3 cp - s3://lagoon-images/$(image).tar.gz - -s3-load = $(foreach image,$(s3-images),[s3-load]-$(image)) -# save all images to s3 -.PHONY: s3-load -s3-load: $(s3-load) -# tag and push of each image -.PHONY: $(s3-load) -$(s3-load): -# remove the prefix '[s3-load]-' first - $(eval image = $(subst [s3-load]-,,$@)) - $(eval image = $(subst __,:,$(image))) - curl -s https://s3.us-east-2.amazonaws.com/lagoon-images/$(image).tar.gz | gunzip -c | docker load - -# Clean all build touches, which will case make to rebuild the Docker Images (Layer caching is -# still active, so this is a very safe command) -clean: - rm -rf build/* - -# Show Lagoon Service Logs -logs: - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) logs --tail=10 -f $(service) - -# Start all Lagoon Services -up: - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d api-db - sleep 20 - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d - -down: - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) down -v - -# kill all containers containing the name "lagoon" -kill: - docker ps --format "{{.Names}}" | grep lagoon | xargs -t -r -n1 docker rm -f -v - -openshift: - $(info the openshift command has been renamed to minishift) - -# Start Local OpenShift Cluster within a docker machine with a given name, also check if the IP -# that has been assigned to the machine is not the default one and then replace the IP in the yaml files with it -minishift: local-dev/minishift/minishift - $(info starting minishift with name $(CI_BUILD_TAG)) - MINISHIFT_ENABLE_EXPERIMENTAL=y ./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) start --cpus $(MINISHIFT_CPUS) --memory $(MINISHIFT_MEMORY) --disk-size $(MINISHIFT_DISK_SIZE) --vm-driver virtualbox --openshift-version="v3.9.0" --extra-clusterup-flags "--service-catalog" -ifeq ($(ARCH), Darwin) - @OPENSHIFT_MACHINE_IP=$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip); \ - echo "replacing IP in local-dev/api-data/01-populate-api-data.gql and docker-compose.yaml with the IP '$$OPENSHIFT_MACHINE_IP'"; \ - sed -i '' -e "s/192.168\.[0-9]\{1,3\}\.[0-9]\{3\}/$${OPENSHIFT_MACHINE_IP}/g" local-dev/api-data/01-populate-api-data.gql docker-compose.yaml; -else - @OPENSHIFT_MACHINE_IP=$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip); \ - echo "replacing IP in local-dev/api-data/01-populate-api-data.gql and docker-compose.yaml with the IP '$$OPENSHIFT_MACHINE_IP'"; \ - sed -i "s/192.168\.[0-9]\{1,3\}\.[0-9]\{3\}/$${OPENSHIFT_MACHINE_IP}/g" local-dev/api-data/01-populate-api-data.gql docker-compose.yaml; -endif - ./local-dev/minishift/minishift ssh -- '/bin/sh -c "sudo sysctl -w vm.max_map_count=262144"' - eval $$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) oc-env); \ - oc login -u system:admin; \ - bash -c "echo '{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"name\":\"docker-registry-external\"},\"spec\":{\"ports\":[{\"port\":5000,\"protocol\":\"TCP\",\"targetPort\":5000,\"nodePort\":30000}],\"selector\":{\"docker-registry\":\"default\"},\"sessionAffinity\":\"None\",\"type\":\"NodePort\"}}' | oc --context="default/$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip | sed 's/\./-/g'):8443/system:admin" create -n default -f -"; \ - oc --context="default/$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip | sed 's/\./-/g'):8443/system:admin" adm policy add-cluster-role-to-user cluster-admin system:anonymous; \ - oc --context="default/$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip | sed 's/\./-/g'):8443/system:admin" adm policy add-cluster-role-to-user cluster-admin developer; - @echo "$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip)" > $@ - @echo "wait 60secs in order to give openshift time to setup it's registry" - sleep 60 - eval $$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) oc-env); \ - for i in {10..30}; do oc --context="default/$$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) ip | sed 's/\./-/g'):8443/system:admin" patch pv pv00$${i} -p '{"spec":{"storageClassName":"bulk"}}'; done; - $(MAKE) minishift/configure-lagoon-local push-docker-host-image - -minishift/login-docker-registry: - eval $$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) oc-env); \ - oc login --insecure-skip-tls-verify -u developer -p developer $$(cat minishift):8443; \ - oc whoami -t | docker login --username developer --password-stdin $$(cat minishift):30000 - -# Configures an openshift to use with Lagoon -.PHONY: openshift-lagoon-setup -openshift-lagoon-setup: -# Only use the minishift provided oc if we don't have one yet (allows system engineers to use their own oc) - if ! which oc; then eval $$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) oc-env); fi; \ - oc -n default set env dc/router -e ROUTER_LOG_LEVEL=info -e ROUTER_SYSLOG_ADDRESS=router-logs.lagoon.svc:5140; \ - oc new-project lagoon; \ - oc adm pod-network make-projects-global lagoon; \ - oc -n lagoon create serviceaccount openshiftbuilddeploy; \ - oc -n lagoon policy add-role-to-user admin -z openshiftbuilddeploy; \ - oc -n lagoon create -f openshift-setup/clusterrole-openshiftbuilddeploy.yaml; \ - oc -n lagoon adm policy add-cluster-role-to-user openshiftbuilddeploy -z openshiftbuilddeploy; \ - oc -n lagoon create -f openshift-setup/shared-resource-viewer.yaml; \ - oc -n lagoon create -f openshift-setup/policybinding.yaml | oc -n lagoon create -f openshift-setup/rolebinding.yaml; \ - oc -n lagoon create serviceaccount docker-host; \ - oc -n lagoon adm policy add-scc-to-user privileged -z docker-host; \ - oc -n lagoon policy add-role-to-user edit -z docker-host; \ - oc -n lagoon create serviceaccount logs-collector; \ - oc -n lagoon adm policy add-cluster-role-to-user cluster-reader -z logs-collector; \ - oc -n lagoon adm policy add-scc-to-user hostaccess -z logs-collector; \ - oc -n lagoon adm policy add-scc-to-user privileged -z logs-collector; \ - oc -n lagoon adm policy add-cluster-role-to-user daemonset-admin -z lagoon-deployer; \ - oc -n lagoon create serviceaccount lagoon-deployer; \ - oc -n lagoon policy add-role-to-user edit -z lagoon-deployer; \ - oc -n lagoon create -f openshift-setup/clusterrole-daemonset-admin.yaml; \ - oc -n lagoon adm policy add-cluster-role-to-user daemonset-admin -z lagoon-deployer; \ - bash -c "oc process -n lagoon -f services/docker-host/docker-host.yaml | oc -n lagoon apply -f -"; \ - echo -e "\n\nAll Setup, use this token as described in the Lagoon Install Documentation:" \ - oc -n lagoon serviceaccounts get-token openshiftbuilddeploy - - -# This calles the regular openshift-lagoon-setup first, which configures our minishift like we configure a real openshift for laggon -# It then overwrite the docker-host deploymentconfig and cronjobs to use our own just builded docker-host images -.PHONY: openshift/configure-lagoon-local -minishift/configure-lagoon-local: openshift-lagoon-setup - eval $$(./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) oc-env); \ - bash -c "oc process -n lagoon -p SERVICE_IMAGE=172.30.1.1:5000/lagoon/docker-host:latest -p REPOSITORY_TO_UPDATE=lagoon -f services/docker-host/docker-host.yaml | oc -n lagoon apply -f -"; \ - oc -n default set env dc/router -e ROUTER_LOG_LEVEL=info -e ROUTER_SYSLOG_ADDRESS=192.168.99.1:5140; \ - -# Stop OpenShift Cluster -.PHONY: minishift/stop -minishift/stop: local-dev/minishift/minishift - ./local-dev/minishift/minishift --profile $(CI_BUILD_TAG) delete --force - rm minishift - -# Stop OpenShift, remove downloaded minishift -.PHONY: openshift/clean -minishift/clean: minishift/stop - rm -rf ./local-dev/minishift/minishift - -# Downloads the correct oc cli client based on if we are on OS X or Linux -local-dev/minishift/minishift: - $(info downloading minishift) - @mkdir -p ./local-dev/minishift -ifeq ($(ARCH), Darwin) - curl -L https://github.com/minishift/minishift/releases/download/v$(MINISHIFT_VERSION)/minishift-$(MINISHIFT_VERSION)-darwin-amd64.tgz | tar xzC local-dev/minishift --strip-components=1 -else - curl -L https://github.com/minishift/minishift/releases/download/v$(MINISHIFT_VERSION)/minishift-$(MINISHIFT_VERSION)-linux-amd64.tgz | tar xzC local-dev/minishift --strip-components=1 -endif - -.PHONY: push-oc-build-deploy-dind -rebuild-push-oc-build-deploy-dind: - rm -rf build/oc-build-deploy-dind - $(MAKE) build/oc-build-deploy-dind [push-minishift]-oc-build-deploy-dind - - - -.PHONY: ui-development -ui-development: build/api build/api-db build/local-api-data-watcher-pusher build/ui build/keycloak build/keycloak-db - IMAGE_REPO=$(CI_BUILD_TAG) docker-compose -p $(CI_BUILD_TAG) up -d api api-db local-api-data-watcher-pusher ui keycloak keycloak-db - diff --git a/README.md b/README.md index 16fbec811..1c0c7d30c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,42 @@ -# amazee.io Lagoon - Docker Build and Deploy System for OpenShift & Kubernetes +

SDP logo

+

Bay is the hosting and infrastructure layer for Single Digital Presence, delivered using amazee.io Lagoon.

+ +# Table of Contents +* [About](#About) + * [amazee.io Lagoon](#amazeeio-lagoon) +* [Use](#use) +* [Contribute](#contribute) +* [Support](#support) +* [License](#license) +* [Attribution](#Attribution) + +# About +Bay is a fully managed platform and hosting environment that provides an open Platform as a Service model managed by SDP. It: + - is an open-source hosting platform based on Lagoon. + - allows agencies to build, test and deliver websites via the cloud. + - is a Kubernetes-based (OpenShift) Docker container hosting platform with auto-scaling, auto-recovery and high-availability at core. + - is based on open-source project Lagoon. + +## amazee.io Lagoon Lagoon solves what developers are dreaming about: A system that allows developers to locally develop their code and their services with Docker and run the exact same system in production. The same Docker images, the same service configurations and the same code. -Please reference our [documentation](https://lagoon.readthedocs.io/) for detailed information on using, developing, and administering Lagoon. +# Use +Learn more from https://lagoon.readthedocs.io/en/latest/ + +# Contribute +[Open an issue](https://github.com/dpc-sdp/bay) on GitHub or submit a pull request with suggested changes. + +# Support +[Digital Engagement, Department of Premier and Cabinet, Victoria, Australia](https://github.com/dpc-sdp) +is a maintainer of this package. + +# License +This project is licensed under [GPL2](https://github.com/dpc-sdp/bay/blob/master/LICENSE) + +# Attribution +Single Digital Presence offers government agencies an open and flexible toolkit to build websites quickly and cost-effectively. +

SDP logo

+ +The Department of Premier and Cabinet partnered with Salsa Digital to deliver Single Digital Presence. As long-term supporters of open government approaches, they were integral to the establishment of SDP as an open source platform. +

Salsa logo

diff --git a/bay/images/Dockerfile.builder b/bay/images/Dockerfile.builder index 22111fda7..e8b19d3fa 100644 --- a/bay/images/Dockerfile.builder +++ b/bay/images/Dockerfile.builder @@ -1,4 +1,4 @@ -FROM amazeeio/php:7.1-cli-drupal +FROM amazeeio/php:7.2-cli-drupal ENV WEBROOT=docroot \ COMPOSER_ALLOW_SUPERUSER=1 \ @@ -11,13 +11,7 @@ RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSI RUN apk update \ && apk del nodejs nodejs-current yarn \ - && apk add nodejs-npm patch rsync --update-cache --repository http://dl-3.alpinelinux.org/alpine/v3.7/main/ \ - && rm -rf /var/cache/apk/* \ - && apk add --update jq clamav clamav-libunrar \ - && rm -rf /var/lib/clamav/daily.cvd \ - && freshclam --no-warnings || true \ - && apk del --no-cache curl \ - && apk add --no-cache "curl=7.61.1-r2" --repository http://dl-cdn.alpinelinux.org/alpine/v3.8/main/ + && apk add nodejs-npm patch rsync --no-cache --repository http://dl-3.alpinelinux.org/alpine/v3.7/main/ # Add common drupal config. RUN mkdir /bay diff --git a/bay/images/Dockerfile.circle b/bay/images/Dockerfile.circle index 80ead7aaa..8e64aab63 100644 --- a/bay/images/Dockerfile.circle +++ b/bay/images/Dockerfile.circle @@ -1,4 +1,4 @@ -FROM php:7.1-cli +FROM php:7.2-cli ENV COMPOSER_ALLOW_SUPERUSER=1 \ DOCKER_VERSION=17.03.2 \ diff --git a/bay/images/Dockerfile.mariadb b/bay/images/Dockerfile.mariadb index 87169e47c..dd7e71b3d 100644 --- a/bay/images/Dockerfile.mariadb +++ b/bay/images/Dockerfile.mariadb @@ -1,7 +1 @@ FROM amazeeio/mariadb-drupal - -USER root -COPY docker/server.cnf /etc/my.cnf.d/server.cnf -RUN fix-permissions /etc/my.cnf.d/ - -USER mysql diff --git a/bay/images/Dockerfile.nginx b/bay/images/Dockerfile.nginx index 833a22700..9e9ecad0c 100644 --- a/bay/images/Dockerfile.nginx +++ b/bay/images/Dockerfile.nginx @@ -3,8 +3,6 @@ FROM amazeeio/nginx-drupal ENV WEBROOT=docroot ENV TZ=Australia/Melbourne -COPY docker/drupal.conf /etc/nginx/conf.d/app.conf - RUN fix-permissions /etc/nginx \ && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone diff --git a/bay/images/Dockerfile.php b/bay/images/Dockerfile.php index f7f9d53ff..68be7e0d4 100644 --- a/bay/images/Dockerfile.php +++ b/bay/images/Dockerfile.php @@ -1,11 +1,4 @@ -FROM amazeeio/php:7.1-fpm - -# Add ClamAV. -RUN apk add --update clamav clamav-libunrar \ - && rm -rf /var/lib/clamav/daily.cvd \ - && freshclam --no-warnings || true \ - && apk del --no-cache curl \ - && apk add --no-cache "curl=7.61.1-r2" --repository http://dl-cdn.alpinelinux.org/alpine/v3.8/main/ +FROM amazeeio/php:7.2-fpm # Add blackfire probe. RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \ @@ -23,6 +16,7 @@ COPY docker/settings.php /bay ENV TZ=Australia/Melbourne + RUN apk add --no-cache tzdata \ && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone diff --git a/bay/images/docker/drupal.conf b/bay/images/docker/drupal.conf deleted file mode 100644 index e97531615..000000000 --- a/bay/images/docker/drupal.conf +++ /dev/null @@ -1,144 +0,0 @@ -### Nginx configuration for Drupal 7 and 8. -server { - include /etc/nginx/conf.d/drupal/server_prepend*.conf; - - listen ${NGINX_LISTEN:-8080} default_server; - - include /etc/nginx/helpers/*.conf; - - root /app/${WEBROOT:-}; - index index.php; - - ## rewriting /index.php to / because after https://www.drupal.org/node/2599326 - ## autocomplete URLs are forced to go to index.php - rewrite ^/index.php / last; - - ## The 'default' location. - location / { - include /etc/nginx/conf.d/drupal/location_prepend*.conf; - - ## Replicate the Apache directive of Drupal standard - ## .htaccess. Disable access to any code files. Return a 404 to curtail - ## information disclosure. Hide also the text files. - location ~* ^(?:.+\.(?:htaccess|make|txt|yml|md|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl|xtmpl)|code-style\.pl)$ { - deny all; - access_log off; - log_not_found off; - } - - ## Expiring per default for four weeks and one second, Drupal will overwrite that if necessary - expires 2628001s; - - ## Disallow access to any dot files, but send the request to Drupal - location ~* /\. { - try_files /dev/null @drupal; - } - - ### Directives for installing drupal. - location ~* ^(/install.php|/core/install.php) { - try_files /dev/null @php; - } - - ## Direct Access to .php files is not alled and is sent to Drupal instead - location ~* ^.+\.php$ { - try_files /dev/null @drupal; - } - - ## Try to find a file with given URL, if not pass to Drupal - try_files $uri @drupal; - - include /etc/nginx/conf.d/drupal/location_append*.conf; - } - - ## Main Drupal Location - location @drupal { - include /etc/nginx/conf.d/drupal/location_drupal_prepend*.conf; - - include /etc/nginx/fastcgi.conf; - fastcgi_param SCRIPT_NAME /index.php; - fastcgi_param SCRIPT_FILENAME $realpath_root/index.php; - fastcgi_pass ${NGINX_FASTCGI_PASS:-php}:9000; - - include /etc/nginx/conf.d/drupal/location_drupal_append*.conf; - } - - ## PHP Location. - ## Warning: This allows to execute any PHP files, use with care! - location @php { - include /etc/nginx/conf.d/drupal/location_php_prepend*.conf; - - include /etc/nginx/fastcgi.conf; - fastcgi_pass ${NGINX_FASTCGI_PASS:-php}:9000; - - include /etc/nginx/conf.d/drupal/location_php_append*.conf; - } - - ## Trying to access private files directly returns a 404. - location /sites/default/files/private/ { - internal; - } - - ## Disallow access to patches directory. - location ^~ /patches { - deny all; - access_log off; - log_not_found off; - } - - ## Disallow access to backup directory. - location ^~ /backup { - deny all; - access_log off; - log_not_found off; - } - - ## Disallow access to vagrant directory. - location ^~ /vagrant { - deny all; - access_log off; - log_not_found off; - } - - ## Disallow access to /core/vendor. - location ^~ /core/vendor { - deny all; - access_log off; - log_not_found off; - } - - ## Disallow access to /vendor. - location ^~ /vendor/ { - deny all; - access_log off; - log_not_found off; - } - - ## Support for the robotstxt module - ## http://drupal.org/project/robotstxt. - location = /robots.txt { - access_log off; - try_files $uri @drupal; - } - - ## Add support for the humanstxt module - ## http://drupal.org/project/humanstxt. - location = /humans.txt { - access_log off; - try_files $uri @drupal; - } - - ## Support for favicon. Return an 1x1 transparent GIF if it doesn't - ## exist. - location = /favicon.ico { - expires 30d; - try_files /favicon.ico @empty; - } - - ## Return an in memory 1x1 transparent GIF. - location @empty { - expires 30d; - empty_gif; - } - - include /etc/nginx/conf.d/drupal/server_append*.conf; -} diff --git a/bay/images/docker/my.cnf b/bay/images/docker/my.cnf deleted file mode 100644 index 9050af9e6..000000000 --- a/bay/images/docker/my.cnf +++ /dev/null @@ -1,43 +0,0 @@ -# The following options will be passed to all MariaDB clients -[client] -port = 3306 -socket = /run/mysqld/mysqld.sock - -# Here follows entries for some specific programs - -# The MariaDB server -[mysqld] -port = 3306 -socket = /run/mysqld/mysqld.sock -character_set_server = utf8 -collation_server = utf8_bin -expire_logs_days = 10 -ignore_db_dirs=backup -innodb_buffer_pool_size = 256M -innodb_default_row_format=dynamic -innodb_file_format = Barracuda -innodb_large_prefix = 1 -innodb_log_buffer_size = 32M -innodb_log_file_size = 100M -join_buffer_size = 2M -key_buffer_size = 16M -max_allowed_packet = 64M -max_binlog_size = 100M -max_connections = 400 -max_heap_table_size = 512M -myisam-recover-options = BACKUP -query_cache_limit = 1M -query_cache_size = 128M -skip-external-locking -skip_name_resolve = 1 -slow_query_log = 1 -slow_query_log_file = /var/log/mysql-slow.log -table_open_cache = 200000 -thread_cache_size = 8 -thread_stack = 256K -tmp_table_size = 512M -tmpdir = /tmp -transaction-isolation = READ-COMMITTED -skip-name-resolve - -!includedir /etc/mysql/conf.d diff --git a/bay/images/docker/server.cnf b/bay/images/docker/server.cnf index 9ec5156fc..728970c8a 100644 --- a/bay/images/docker/server.cnf +++ b/bay/images/docker/server.cnf @@ -1,14 +1,24 @@ +# The following options will be passed to all MariaDB clients +[client] +port = 3306 +socket = /run/mysqld/mysqld.sock + +# Here follows entries for some specific programs + +# The MariaDB server [mysqld] -character_set_server = utf8 -collation_server = utf8_bin +port = 3306 +socket = /run/mysqld/mysqld.sock +character_set_server = ${MARIADB_CHARSET:-utf8mb4} +collation_server = ${MARIADB_COLLATION:-utf8mb4_bin} expire_logs_days = 10 -ignore_db_dirs= lost+found +ignore_db_dirs=backup innodb_buffer_pool_size = ${MARIADB_INNODB_BUFFER_POOL_SIZE:-256M} +innodb_buffer_pool_instances = ${MARIADB_INNODB_BUFFER_POOL_INSTANCES:-1} innodb_file_format = Barracuda -innodb_file_per_table = false innodb_large_prefix = 1 innodb_log_buffer_size = 32M -innodb_log_file_size = 100M +innodb_log_file_size = ${MARIADB_INNODB_LOG_FILE_SIZE:-64M} join_buffer_size = 2M key_buffer_size = 16M max_allowed_packet = 64M @@ -16,19 +26,18 @@ max_binlog_size = 100M max_connections = 400 max_heap_table_size = 512M myisam-recover-options = BACKUP -query_cache_limit = 1M -query_cache_size = 128M +query_cache_size = 0 +query_cache_type = 0 skip-external-locking skip_name_resolve = 1 -slow_query_log = 1 -slow_query_log_file = /var/log/mysql-slow.log table_open_cache = 200000 thread_cache_size = 8 thread_stack = 256K tmp_table_size = 512M tmpdir = /tmp transaction-isolation = READ-COMMITTED -socket = /tmp/mysql.sock +skip-name-resolve +optimizer_search_depth = 0 +innodb_flush_log_at_trx_commit = 0 -[isamchk] -key_buffer_size = 16M \ No newline at end of file +!includedir /etc/mysql/conf.d diff --git a/bay/images/docker/settings.php b/bay/images/docker/settings.php index 22f1edeaf..566810841 100755 --- a/bay/images/docker/settings.php +++ b/bay/images/docker/settings.php @@ -47,6 +47,9 @@ // Disable local split. $config['config_split.config_split.local']['status'] = FALSE; +// Set Stage File Proxy to use hotlink platform-wide +$config['stage_file_proxy.settings']['hotlink'] = TRUE; + if (getenv('ENABLE_REDIS')) { $redis_host = getenv('REDIS_HOST') ?: 'redis'; // Kube service discovery sets REDIS_PORT to a TCP address. @@ -171,3 +174,13 @@ $settings['container_yamls'][] = $settings_path . '/envs/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '/services.yml'; } } + +// Include branch specific settings and services files. +if (getenv('LAGOON_GIT_SAFE_BRANCH')) { + if (file_exists($settings_path . '/branch/' . getenv('LAGOON_GIT_SAFE_BRANCH') . '/settings.php')) { + include $settings_path . '/branch/' . getenv('LAGOON_GIT_SAFE_BRANCH') . '/settings.php'; + } + if (file_exists($settings_path . '/branch/' . getenv('LAGOON_GIT_SAFE_BRANCH') . '/services.yml')) { + $settings['container_yamls'][] = $settings_path . '/branch/' . getenv('LAGOON_GIT_SAFE_BRANCH') . '/services.yml'; + } +} diff --git a/build/.gitkeep b/build/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/charts-values/clair/values.yaml b/charts-values/clair/values.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/charts-values/grafana/values.yaml b/charts-values/grafana/values.yaml deleted file mode 100644 index ce21bc44f..000000000 --- a/charts-values/grafana/values.yaml +++ /dev/null @@ -1,19024 +0,0 @@ -openshift: true - -server: - adminPassword: changeme - - image: "grafana/grafana:4.6.3" - - ingress: - hosts: - - grafana.lagoon.vicsdp.amazee.io - - persistentVolume: - enabled: true - - service: - annotations: - prometheus.io/scrape: 'true' - - setDatasource: - enabled: true - image: appropriate/curl:latest - restartPolicy: OnFailure - datasource: - name: prometheus - type: prometheus - url: "http://prometheus-dpc-prometheus-dpc-server:80" - isDefault: true - - # This is an extension of the standard Helm Chart - setNotificationChannel: - enabled: true - image: appropriate/curl:latest - restartPolicy: OnFailure - channel: - name: "salsa_dpc #bay-build" - type: slack - url: "https://hooks.slack.com/services/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" - isDefault: true - - # This is an extension of the standard Helm Chart - setGenericOauth: - enabled: true - clientId: XXXXXXXXXXXX - clientSecret: YYYYYYYYYYYY - scopes: email user_data - authUrl: https://citopro.au.auth0.com/authorize - tokenUrl: https://citopro.au.auth0.com/oauth/token - apiUrl: https://citopro.au.auth0.com/userinfo - #allowedDomains: mycompany.com mycompany.org - allowSignUp: true - - # This is an extension of the standard Helm Chart - serverDomain: aec1ad6b.ngrok.io - serverRootUrl: "%(protocol)s://%(domain)s/" - -serverConfigFile: - grafana.ini: | - ; instance_name = ${HOSTNAME} - [paths] - data = /var/lib/grafana/data - logs = /var/log/grafana - plugins = /var/lib/grafana/plugins - - [server] - ;protocol = http - ;http_addr = - ;http_port = 3000 - ;domain = localhost - ;domain = e947ef49.ngrok.io - ;enforce_domain = false - ;root_url = %(protocol)s://%(domain)s:%(http_port)s/ - ;root_url = %(protocol)s://%(domain)s/ - ;router_logging = false - ;static_root_path = public - ;enable_gzip = false - ;cert_file = - ;cert_key = - - [database] - ;type = sqlite3 - ;host = 127.0.0.1:3306 - ;name = grafana - ;user = root - ;password = - ;ssl_mode = disable - ;path = grafana.db - - [session] - ;provider = file - ;provider_config = sessions - ;cookie_name = grafana_sess - ;cookie_secure = false - ;session_life_time = 86400 - - [analytics] - ;reporting_enabled = true - check_for_updates = true - ;google_analytics_ua_id = - - [security] - ;admin_user = admin - ;admin_password = admin - ;secret_key = SW2YcwTIb9zpOOhoPsMm - ;login_remember_days = 7 - ;cookie_username = grafana_user - ;cookie_remember_name = grafana_remember - ;disable_gravatar = false - ;data_source_proxy_whitelist = - - [snapshots] - ;external_enabled = true - ;external_snapshot_url = https://snapshots-origin.raintank.io - ;external_snapshot_name = Publish to snapshot.raintank.io - - [users] - ;allow_sign_up = true - ;allow_org_create = true - ;auto_assign_org = true - ;auto_assign_org_role = Viewer - ;login_hint = email or username - ;default_theme = dark - - [auth.generic_oauth] - ;enabled = true - ;client_id = bXd7yxVqxsOOSUfGbWv2Gj66YGDD6YSa - ;client_secret = SnHw1_pA8PBReUPtsPH82H2kFCLebeTUC-CxPyDkD-DuU36wV_gZfxE1jZZsJjk- - ;scopes = email user_data - ;auth_url = https://citopro.au.auth0.com/authorize - ;token_url = https://citopro.au.auth0.com/oauth/token - ;api_url = https://citopro.au.auth0.com/userinfo - ;allowed_domains = mycompany.com mycompany.org - ;allow_sign_up = true - - [auth.anonymous] - ;enabled = false - ;org_name = Main Org. - ;org_role = Viewer - - [auth.github] - ;enabled = false - ;allow_sign_up = false - ;client_id = some_id - ;client_secret = some_secret - ;scopes = user:email,read:org - ;auth_url = https://github.com/login/oauth/authorize - ;token_url = https://github.com/login/oauth/access_token - ;api_url = https://api.github.com/user - ;team_ids = - ;allowed_organizations = - - [auth.google] - ;enabled = false - ;allow_sign_up = false - ;client_id = some_client_id - ;client_secret = some_client_secret - ;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email - ;auth_url = https://accounts.google.com/o/oauth2/auth - ;token_url = https://accounts.google.com/o/oauth2/token - ;api_url = https://www.googleapis.com/oauth2/v1/userinfo - ;allowed_domains = - - [auth.proxy] - ;enabled = false - ;header_name = X-WEBAUTH-USER - ;header_property = username - ;auto_sign_up = true - - [auth.basic] - ;enabled = true - - [auth.ldap] - ;enabled = false - ;config_file = /etc/grafana/ldap.toml - - [smtp] - ;enabled = false - ;host = localhost:25 - ;user = - ;password = - ;cert_file = - ;key_file = - ;skip_verify = false - ;from_address = admin@grafana.localhost - - [emails] - ;welcome_email_on_sign_up = false - - [log] - mode = console - level = info - - [log.console] - ;level = - ;format = console - - [event_publisher] - ;enabled = false - ;rabbitmq_url = amqp://localhost/ - ;exchange = grafana_events - - [dashboards.json] - enabled = true - path = /var/lib/grafana/dashboards - - [metrics] - ;enabled = true - ;interval_seconds = 10 - - ; [metrics.graphite] - ; address = localhost:2003 - ; prefix = prod.grafana.%(instance_name)s. - - [grafana_net] - url = https://grafana.net - - -serverDashboardFiles: - alerts.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "panel", - "id": "alertlist", - "name": "Alert List", - "version": "" - }, - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": 250, - "panels": [ - { - "id": 2, - "limit": 10, - "links": [], - "onlyAlertsOnDashboard": false, - "show": "current", - "sortOrder": 1, - "span": 12, - "stateFilter": [], - "title": "Current Alerts", - "type": "alertlist" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 223, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 50 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "The memory used within the Kubernetes cluster is above the defined threshold.", - "name": "Cluster Memory Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "description": "Percentage of memory used across the cluster.", - "fill": 1, - "id": 1, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal) * 100 ", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Percentage memory used", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 50 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Cluster Memory Used", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Alerts", - "version": 8 - } - kubernetes-capacity-planning.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_cpu{mode=\"idle\"}[2m])) * 100", - "hide": false, - "intervalFactor": 10, - "legendFormat": "", - "refId": "A", - "step": 50 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_load1)", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load5)", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load15)", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)", - "intervalFactor": 2, - "legendFormat": "memory usage", - "metric": "memo", - "refId": "A", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Buffers)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "memo", - "refId": "B", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Cached)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "memo", - "refId": "C", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_MemFree)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "memo", - "refId": "D", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "((sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal)) * 100", - "intervalFactor": 2, - "metric": "", - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "246px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_disk_bytes_read[5m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(rate(node_disk_bytes_written[5m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum(rate(node_disk_io_time_ms[5m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 12, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(node_filesystem_size{device!=\"rootfs\"}) - sum(node_filesystem_free{device!=\"rootfs\"})) / sum(node_filesystem_size{device!=\"rootfs\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_network_receive_bytes{device!~\"lo\"}[5m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_network_transmit_bytes{device!~\"lo\"}[5m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "276px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 11, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_info)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Current number of Pods", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_node_status_capacity_pods)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Maximum capacity of pods", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Cluster Pod Utilization", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "100 - (sum(kube_node_status_capacity_pods) - sum(kube_pod_info)) / sum(kube_node_status_capacity_pods) * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Pod Utilization", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Capacity Planning", - "version": 3 - } - kubernetes-control-plane-status.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - }, - { - "type": "panel", - "id": "table", - "name": "Table", - "version": "" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 1, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(up{job=\"kubernetes-apiservers\"} == 1) / sum(up{job=\"kubernetes-apiservers\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "50, 80", - "title": "API Servers UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(up{job=\"kubernetes-nodes\"} == 1) / sum(up{job=\"kubernetes-nodes\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "50, 80", - "title": "Nodes UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "columns": [], - "datasource": "prometheus", - "fontSize": "100%", - "id": 9, - "links": [], - "pageSize": null, - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "span": 6, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "link": false, - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Instance", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 0, - "pattern": "instance", - "thresholds": [], - "type": "number", - "unit": "none" - } - ], - "targets": [ - { - "expr": "sum(up{job=\"kubernetes-nodes\"}) by (instance)", - "format": "table", - "hide": false, - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "title": "Nodes Up", - "transform": "table", - "type": "table" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Control Plane Status", - "version": 4 - } - kubernetes-deployments.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "200px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}) / 1024^3", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",job!=\"kubernetes-apiservers\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",job!=\"kubernetes-apiservers\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_deployment_spec_replicas", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_status_observed_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_metadata_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(kube_deployment_status_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "current replicas", - "refId": "A", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_deployment_status_replicas_unavailable{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "unavailable", - "refId": "C", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_updated{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "updated", - "refId": "D", - "step": 30 - }, - { - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".*", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "deployment_namespace", - "options": [], - "query": "label_values(kube_deployment_metadata_generation, namespace)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": null, - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Deployment", - "multi": false, - "name": "deployment_name", - "options": [], - "query": "label_values(kube_deployment_metadata_generation{namespace=\"$deployment_namespace\"}, deployment)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "deployment", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Deployments", - "version": 6 - } - kubernetes-pods.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "", - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": null, - "panels": [ - { - "content": "

$phase

", - "height": "55px", - "id": 3, - "links": [], - "mode": "html", - "span": 4, - "title": "Status", - "type": "text" - }, - { - "content": "

$pod_ip

", - "height": "55px", - "id": 9, - "links": [], - "mode": "html", - "span": 4, - "title": "IP", - "type": "text" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_scheduled{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Scheduled", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 18, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",pod_name=~\"$pod\",job!=\"kubernetes-apiservers\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "prometheus", - "format": "decbytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 19, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$namespace\",pod_name=~\"$pod\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Current Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "prometheus", - "decimals": 2, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 20, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$namespace\",pod_name=~\"$pod\"}[2m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$namespace\",pod_name=~\"$pod\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg Network", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "prometheus", - "decimals": 2, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 21, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) + sum(rate(container_fs_reads_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg Disk", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Pod Status", - "titleSize": "h5" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{pod_name=~\"^$pod$\",job!=\"kubernetes-nodes\"}[2m])) by (pod_name)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Pod NW Transmit", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_network_receive_bytes_total{pod_name=~\"^$pod$\",job!=\"kubernetes-nodes\"}[2m])) by (pod_name)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Pod NW Receive", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_running{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Running", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_restarts{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Restarts", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 1, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_terminated{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Terminated", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_waiting{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Waiting", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Container Status", - "titleSize": "h5" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 12, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": "container", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=~\"^$namespace$\",pod_name=~\"^$pod$\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Actual: {{ container_name }}", - "refId": "A" - }, - { - "expr": "kube_pod_container_resource_requests_memory_bytes{pod=~\"^$pod$\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Requested: {{ container }}", - "refId": "B" - }, - { - "expr": "kube_pod_container_resource_limits_memory_bytes{pod=~\"^$pod$\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Limits: {{ container }}", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Memory Usage", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name) ", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container CPU Usage Seconds", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Disk Write", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "fill": 1, - "id": 17, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_reads_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Disk Read", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Pod", - "multi": false, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "prometheus", - "hide": 2, - "includeAll": false, - "label": "Pod IP", - "multi": false, - "name": "pod_ip", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, pod_ip)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 2, - "includeAll": false, - "label": "Phase", - "multi": false, - "name": "phase", - "options": [], - "query": "query_result(kube_pod_status_phase{namespace=~\"^$namespace$\", pod=~\"^$pod$\"} == 1)", - "refresh": 2, - "regex": "/.*phase=\"(.+?)\".*/", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "prometheus", - "hide": 2, - "includeAll": false, - "label": "Container", - "multi": false, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, container)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes Pods", - "version": 27 - } - kubernetes-resource-requests.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(sum(kube_node_status_allocatable_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable CPU Cores", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested CPU Cores", - "refId": "B", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Cores", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "CPU Cores", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance)) / min(sum(kube_node_status_allocatable_cpu_cores) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "CPU Cores", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "CPU Cores", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(sum(kube_node_status_allocatable_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable Memory", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested Memory", - "refId": "B", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "Memory", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance)) / min(sum(kube_node_status_allocatable_memory_bytes) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "Memory", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Memory", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource Requests", - "version": 2 - } - kubernetes-statefulsets.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "200px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}) / 1024^3", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_statefulset_replicas", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_status_observed_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_metadata_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": "None", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": false, - "name": "statefulset_namespace", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "None", - "type": "query", - "useTags": false - }, - { - "allValue": "None", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": true, - "label": "StatefulSet", - "multi": false, - "name": "statefulset_name", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation{namespace=\"$statefulset_namespace\"}, statefulset)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "statefulset", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes StatefulSets", - "version": 4 - } - mysql-cross-server-graphs.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_connections{alias=~\"$host\"}[$interval]) or irate(mysql_global_status_connections{alias=~\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=~\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=~\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_queries%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load1{alias=~\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [ - { - "colorMode": "custom", - "line": true, - "lineColor": "rgb(241, 34, 15)", - "op": "gt", - "value": 15 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "(node_memory_MemTotal{alias=~\"$host\"} - (node_memory_MemAvailable{alias=~\"$host\"} or (node_memory_MemFree{alias=~\"$host\"} + node_memory_Buffers{alias=~\"$host\"} + node_memory_Cached{alias=~\"$host\"}))) / node_memory_MemTotal{alias=~\"$host\"} * 100", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [ - { - "colorMode": "custom", - "line": true, - "lineColor": "rgb(248, 8, 48)", - "op": "gt", - "value": 95 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(mysql_global_status_bytes_received{alias=~\"$host\"}[$interval]) + rate(mysql_global_status_bytes_sent{alias=~\"$host\"}[$interval])) or (irate(mysql_global_status_bytes_received{alias=~\"$host\"}[5m]) + irate(mysql_global_status_bytes_sent{alias=~\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Traffic", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_receive_bytes{alias=~\"$host\", device!=\"lo\"}[$interval]) + rate(node_network_transmit_bytes{alias=~\"$host\", device!=\"lo\"}[$interval])) by (alias) or sum(irate(node_network_receive_bytes{alias=~\"$host\", device!=\"lo\"}[5m]) + irate(node_network_transmit_bytes{alias=~\"$host\", device!=\"lo\"}[5m])) by (alias)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "height": "0", - "id": 9, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_version_info{alias=~\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "{{ alias }} | {{ version }} | {{ version_comment }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_uname_info%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2014%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Info", - "tooltip": { - "msResolution": false, - "shared": false, - "sort": 0, - "value_type": "cumulative" - }, - "transparent": true, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": false, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "height": "0", - "id": 5, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_uname_info{alias=~\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "{{ alias }} | Hostname: {{ nodename }} | Kernel: {{ release }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_uname_info%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2014%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Info", - "tooltip": { - "msResolution": false, - "shared": false, - "sort": 0, - "value_type": "cumulative" - }, - "transparent": true, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": false, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Cross-Server Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "OS", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "regex": "", - "type": "interval" - }, - { - "allFormat": "pipe", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "multiFormat": "pipe", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Cross Server Graphs | Percona App", - "version": 1 - } - mysql-disk-performance.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "content": "You can click on an individual disk device on the legend to filter on it or multiple ones by holding Alt button.", - "datasource": "prometheus", - "editable": true, - "error": false, - "height": "50px", - "id": 8, - "links": [], - "mode": "text", - "span": 12, - "style": {}, - "title": "", - "transparent": true, - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ms", - "label": "", - "logBase": 2, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_reads_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_writes_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "iops", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_bytes_read{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_bytes_read{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_bytes_written{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_bytes_written{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Bandwidth", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A7%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A7%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_io_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_io_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_io_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilization", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(1 + rate(node_disk_reads_merged{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (1 + irate(node_disk_reads_merged{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read Ratio: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_reads_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(1 + rate(node_disk_writes_merged{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (1 + irate(node_disk_writes_merged{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write Ratio: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_writes_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Operations Merge Ratio", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - "Read IO size: sdb": "#2F575E", - "Read: sdb": "#3F6833" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_sectors_read{alias=\"$host\", device=~\"$device\"}[$interval]) * 512 / rate(node_disk_reads_completed{alias=\"$host\", device=~\"$device\"}[$interval]) or irate(node_disk_sectors_read{alias=\"$host\", device=~\"$device\"}[5m]) * 512 / irate(node_disk_reads_completed{alias=\"$host\", device=~\"$device\"}[5m]) ", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read size: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_read%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_sectors_written{alias=\"$host\", device=~\"$device\"}[$interval]) * 512 / rate(node_disk_writes_completed{alias=\"$host\", device=~\"$device\"}[$interval]) or irate(node_disk_sectors_written{alias=\"$host\", device=~\"$device\"}[5m]) * 512 / irate(node_disk_writes_completed{alias=\"$host\", device=~\"$device\"}[5m]) ", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write size: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_written%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Disk Stats", - "titleSize": "h6" - }, - { - "collapse": true, - "height": "250px", - "panels": [ - { - "content": "Disk Performance Dashboard is designed to provide quick overview of disk IO utilization and performance.\n\n`Disk Latency` - Shows average latency for Reads and Writes IO Devices. Higher than typical latency for highly loaded storage indicates saturation (overload) and is frequent cause of performance problems. Higher than normal latency also can indicate internal storage problems.\n\n`Disk Operations` - Shows amount of physical IOs (reads and writes) different devices are serving. Spikes in number of IOs served often corresponds to performance problems due to IO subsystem overload.\n\n`Disk Bandwidth` - Shows volume of reads and writes the storage is handling. This can be better measure of IO capacity usage for network attached and SSD storage as it is often bandwidth limited. Amount of data being written to the disk can be used to estimate Flash storage life time.\n\n`Disk Load` - Disk Load shows how much disk was loaded for reads or writes as average number of outstanding requests at different period of time. High disk load is a good measure of actual storage utilization. Different storage types handle load differently - some will show latency increases on low loads others can handle higher load with no problems.\n\n`Disk IO Utilization` - Shows disk Utilization as percent of the time when there was at least one IO request in flight. It is designed to match utilization available in iostat tool. It is not very good measure of true IO Capacity Utilization. Consider looking at IO latency and Disk Load Graphs instead.\n\n`Disk Operations Merge Ratio` - Shows how effectively Operating System is able to merge logical IO requests into physical requests. This is a good measure of the IO locality which can be used for workload characterization. \n\n`Disk IO Size` - Shows average size of a single disk operation.", - "datasource": "prometheus", - "editable": true, - "error": false, - "id": 19, - "isNew": true, - "links": [], - "mode": "markdown", - "span": 12, - "style": {}, - "title": "", - "type": "text" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "HELP", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": true, - "label": "Device", - "multi": true, - "multiFormat": "regex values", - "name": "device", - "options": [], - "query": "label_values(node_disk_reads_completed{alias=\"$host\", device!~\"dm-.+\"}, device)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Disk Performance | Percona App", - "version": 1 - } - mysql-galera-graphs.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_local_recv_queue{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Receive Queue", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_local_send_queue{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Send Queue", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Replication Queues", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_cluster_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Cluster Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_recv{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_sent{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_paused{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Paused", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Flow Control", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Flow Control. This graph shows the number of FC_PAUSE events sent/received. They are sent by a node when its replication queue gets too full. If a node is sending out FC messages it indicates the problem.", - "datasource": "prometheus", - "editable": true, - "error": false, - "id": 46, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_local_cert_failures{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_local_cert_failures{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Local Cert Failures", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_local_bf_aborts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_local_bf_aborts{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Local Bf Aborts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writing Conflicts", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Writing Conflicts. This graphs shows the number of local transactions being committed on this node that failed certification (some other node had a commit that conflicted with ours) – client received deadlock error on commit and also the number of local transactions in flight on this node that were aborted because they locked something an applier thread needed – deadlock error anywhere in an open transaction. The spikes on the graph may indicate writing to the same table potentially the same rows from 2 nodes.\n", - "datasource": "prometheus", - "editable": true, - "error": false, - "id": 43, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_apply_window{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Apply Window", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_commit_window{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Commit Window", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_cert_deps_distance{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Cert Deps Distance", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Parallelization Efficiency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Parallelization Efficiency. This graph shows the average distances between highest and lowest seqno that are concurrently applied, commited and can be possibly applied in parallel (potential degree of parallelization).\n", - "datasource": "prometheus", - "editable": true, - "error": false, - "id": 44, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Transactions Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Transactions Replicated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Count", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_wsrep_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[5m]) / irate(mysql_global_status_wsrep_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Incoming Transaction Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[5m]) / irate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Replicating Transaction Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_threads_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Replicated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Network Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Galera Graphs", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "MySQL", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Galera Graphs | Percona App", - "version": 1 - } - mysql-innodb-metrics.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": { - "Max Checkpoint Age": "#BF1B00", - "Uncheckpointed Bytes": "#E0752D" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Max Checkpoint Age", - "color": "#BF1B00", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_checkpoint_age{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Uncheckpointed Bytes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_checkpoint_max_age{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Checkpoint Age", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Checkpoint Age", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "130px", - "id": 4, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_buffer_pool_size{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_innodb_buffer_pool_size%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-3%206%3A28%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "90,95", - "title": "InnoDB Buffer Pool Size", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "128px", - "id": 5, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "repeat": null, - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(mysql_global_variables_innodb_buffer_pool_size{alias=\"$host\"} * 100) / on (alias) node_memory_MemTotal{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22(mysql_global_variables_innodb_buffer_pool_size%7Balias%3D%5C%22%24host%5C%22%7D%20*%20100)%20%2F%20on%20(alias)%20node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A15%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "40,80", - "title": "Buffer Pool Size of Total RAM", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_max_trx_id{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_max_trx_id{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "InnoDB Transactions", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_history_list_length{alias=\"$host\"} or mysql_info_schema_innodb_metrics_transaction_trx_rseg_history_len{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "History Length", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_max_purge_lag{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Purge Lag", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Transactions", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 37, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Total Size of InnoDB Log Files", - "bars": false, - "color": "#E24D42", - "fill": 0, - "lines": true - }, - { - "alias": "Data Written", - "color": "#E0752D" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_innodb_os_log_written{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Data Written", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_log_files_in_group{alias=\"$host\"} * mysql_global_variables_innodb_log_file_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Total Size of InnoDB Log Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "InnoDB Log File Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_reads{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_reads{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Reads", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_fsyncs{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_fsyncs{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Fsyncs", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_log_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_log_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Log Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - "Avg Row Lock Wait Time": "#BF1B00" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Avg Row Lock Wait Time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Row Lock Waits", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[$interval])/1000 or irate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Row Lock Wait Load", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[$interval])/rate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[5m])/irate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Avg Row Lock Wait Time", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Lock Time", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "ms" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "General", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_buffer_pool_bytes_data{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Total", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_buffer_pool_bytes_dirty{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Dirty", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Content", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_buffer_pool_pages{alias=\"$host\", state!=\"dirty\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Pages", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_created{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_created{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Created", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_read{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_read{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Read", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_written{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_written{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Written", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_buffer_pool_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_buffer_pool_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_buffer_pool_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_buffer_pool_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Requests", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Buffer Pool", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": { - "Uncheckpointed Bytes": "#E0752D" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_ibuf_segment_size{alias=\"$host\"} * mysql_global_status_innodb_page_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Allocated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(mysql_global_status_innodb_ibuf_segment_size{alias=\"$host\"} - mysql_global_status_innodb_ibuf_free_list{alias=\"$host\"})*mysql_global_status_innodb_page_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Change Buffer", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merges{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merges{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merges", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_inserts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_inserts{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Inserts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_deletes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_deletes{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Deletes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_delete_marks{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_delete_marks{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Delete Marks", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Change Buffer Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Change/Insert Buffer", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 44, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_info_schema_innodb_metrics_recovery_log_lsn_current{alias=\"$host\"}*0 + mysql_global_variables_innodb_log_buffer_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "mysql_info_schema_innodb_metrics_recovery_log_lsn_current{alias=\"$host\"} - mysql_info_schema_innodb_metrics_recovery_log_lsn_last_flush{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Log Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "bytes", - "short" - ], - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 43, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Ibuf Merge Ratio", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Insert", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Delete", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Delete Mark", - "refId": "C", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Merges", - "refId": "D", - "step": 300 - }, - { - "expr": "(rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval])+rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval])+rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]))/rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or (irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])+irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])+irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m]))/irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Merge Ratio", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Change Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "short" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_upd_exist_or_extern_records_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_upd_exist_or_extern_records_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Updates Purged", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_del_mark_records_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_del_mark_records_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Deletes Purged", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_undo_log_pages_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_undo_log_pages_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Purged", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Purge Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "short" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - "Avg Row Lock Wait Time": "#BF1B00" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 47, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_transaction_trx_rw_commits_total[$interval])/rate(mysql_global_status_innodb_log_writes[$interval]) or irate(mysql_info_schema_innodb_metrics_transaction_trx_rw_commits_total[5m])/irate(mysql_global_status_innodb_log_writes[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Group Commit Batch Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Group Commit Batch Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "ms" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Performance", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "MySQL", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL InnoDB Metrics | Percona App", - "version": 1 - } - mysql-myisam-metrics.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Reads", - "fill": 0 - }, - { - "alias": "Key Writes", - "fill": 0, - "transform": "negative-Y" - }, - { - "alias": "Key Write Requests", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_reads{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_reads{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Reads", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Read Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Write Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Indexes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Blocks Not Flushed", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_key_buffer_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Buffer Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_key_buffer_size{alias=\"$host\"} - mysql_global_status_key_blocks_unused{alias=\"$host\"} * mysql_global_variables_key_cache_block_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Blocks Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_key_blocks_not_flushed{alias=\"$host\"} * mysql_global_variables_key_cache_block_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Blocks Not Flushed", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Key Cache", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Reads", - "fill": 0 - }, - { - "alias": "Key Writes", - "fill": 0, - "transform": "negative-Y" - }, - { - "alias": "Key Write Requests", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 7, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_reads{alias=\"$host\"}[$interval]) / rate(mysql_global_status_key_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_reads{alias=\"$host\"}[5m]) / irate(mysql_global_status_key_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Read Ratio", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_writes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_key_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_writes{alias=\"$host\"}[5m]) / irate(mysql_global_status_key_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Write Ratio", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Key Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "The `Key_reads/Key_read_requests` ratio should normally be less than 0.01.\n\nThe `Key_writes/Key_write_requests` ratio is usually near 1 if you are using mostly updates and deletes, but might be much smaller if you tend to do updates that affect many rows at the same time or if you are using the `DELAY_KEY_WRITE` table option.", - "datasource": "prometheus", - "editable": true, - "error": false, - "height": "", - "id": 23, - "links": [], - "mode": "markdown", - "span": 5, - "style": {}, - "title": "", - "type": "text" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "InnoDB Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL MyISAM Metrics | Percona App", - "version": 1 - } - mysql-overview.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Max Connections", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_connections{alias=\"$host\"}[$interval]) or irate(mysql_global_status_connections{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_max_used_connections{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Used Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_max_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_max_connections{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_max_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "decimals": 1, - "editable": true, - "error": false, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "130px", - "id": 12, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "s", - "postfixFontSize": "80%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_uptime{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_uptime%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A42%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "300,3600", - "title": "MySQL Uptime", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "format": "short", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "128px", - "id": 13, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_queries%7Balias%3D%5C%22%24host%5C%22%7D%20%2F%20mysql_global_status_uptime%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "35,75", - "title": "Current QPS", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Threads Running", - "color": "#E24D42" - }, - { - "alias": "Threads Connected", - "color": "#EAB839" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_connected{alias=\"$host\"}", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Connected", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_connected%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_running{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Running", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Active Threads", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Threads Created", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_thread_cache_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Thread Cache Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_thread_cache_size%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_cached{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_threads_created{alias=\"$host\"}[$interval]) or irate(mysql_global_status_threads_created{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Created", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_threads_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Thread Cache", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 32, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_table_locks_immediate{alias=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_immediate{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Locks Immediate", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_table_locks_waited{alias=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_waited{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Locks Waited", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Table Locks", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_tables%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_disk_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_disk_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Disk Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_disk_tables%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_files{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_files{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_files%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Temporary Objects", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_full_join{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_join{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Full Join", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_full_join%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_full_range_join{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_range_join{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Full Range Join", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_full_range_join%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_range{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_range{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Range", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_range%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_range_check{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_range_check{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Range Check", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_range_check%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_scan{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_scan{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Scan", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_scan%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Select Types", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 30, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_rows{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_rows{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Rows", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_rows%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A36%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_range{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_range{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Range", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_range%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A36%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_merge_passes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_merge_passes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Merge Passes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_merge_passes%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A37%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_scan{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_scan{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Scan", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_scan%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A37%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Sorts", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_bytes_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_bytes_sent{alias=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_sent{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_bytes_received{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_bytes_sent{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "MySQL Network Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 47, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_aborted_connects{alias=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_connects{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Aborted Connects (attempts)", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_aborted_clients{alias=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_clients{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Aborted Clients (timeout)", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Aborted Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 48, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_slow_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_slow_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Slow Queries", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Slow Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "General Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_commands_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{alias=\"$host\"}[5m])>0)", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_commands_total%7Bcommand%3D%5C%22select%5C%22%2C%20alias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A28%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top Command Counters", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, increase(mysql_global_status_commands_total{alias=\"$host\"}[1h])>0)", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20rate(mysql_global_status_commands_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-10-12%207%3A5%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Top Command Counters Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_handlers_total{alias=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{alias=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_read_rnd_next%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A0%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "J", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_handlers_total{alias=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{alias=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_commit%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Transaction Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_info_schema_threads{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_info_schema_threads{alias=\"$host\"}[5m])>0)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20mysql_info_schema_threads%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-12%208%3A32%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top Process States", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 49, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, increase(mysql_info_schema_threads{alias=\"$host\"}[1h])>0)", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20rate(mysql_global_status_commands_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-10-12%207%3A5%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Top Processes Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Command, Handlers, Processes", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_qcache_free_memory{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Free Memory", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "F", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_query_cache_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Query Cache Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Query Cache Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "", - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_hits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_hits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Hits", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_inserts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_inserts{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inserts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_not_cached{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_not_cached{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Not Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_lowmem_prunes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_lowmem_prunes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Prunes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "F", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_qcache_queries_in_cache{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Queries in Cache", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Query Cache Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Query Cache", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 43, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_opened_files{alias=\"$host\"}[$interval]) or irate(mysql_global_status_opened_files{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Openings", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL File Openings", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_open_files{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_open_files_limit{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Files Limit", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Open Files", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 44, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_opened_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_opened_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Openings", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Table Openings", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_open_tables{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_table_open_cache{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Open Cache", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Open Tables", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Files and Tables", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL Overview | Percona App", - "version": 1 - } - mysql-summary.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "260px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\"}[$interval])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\"}[5m])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ mode }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Processes blocked waiting for I/O to complete", - "color": "#E24D42" - }, - { - "alias": "Processes in runnable state", - "color": "#6ED0E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_running{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Processes in runnable state", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_blocked{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Processes blocked waiting for I/O to complete", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_blocked%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Processes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_receive_bytes{alias=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_receive_bytes{alias=\"$host\", device!=\"lo\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_transmit_bytes{alias=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_transmit_bytes{alias=\"$host\", device!=\"lo\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 36, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_read_time_ms{device!~\"dm-.+\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device!~\"dm-.+\", alias=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device!~\"dm-.+\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device!~\"dm-.+\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_write_time_ms{device!~\"dm-.+\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device!~\"dm-.+\", alias=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device!~\"dm-.+\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device!~\"dm-.+\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ms", - "label": "", - "logBase": 2, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 35, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Queries", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "270px", - "id": 34, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 32, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_commands_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{alias=\"$host\"}[5m])>0)", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_commands_total%7Bcommand%3D%5C%22select%5C%22%2C%20alias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A28%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top MySQL Commands", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 33, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_handlers_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_handlers_total{alias=\"$host\"}[5m])>0)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_read_rnd_next%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A0%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "J", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top MySQL Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "MySQL Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Summary Dashboard | Percona App", - "version": 1 - } - mysql-trends.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval])) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m])) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval] offset 1d)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m] offset 1d)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval] offset 1w)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m] offset 1w)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 37, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval] offset 1d) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m] offset 1d) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval] offset 1w) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m] offset 1w) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Read Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval] offset 1d) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m] offset 1d) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval] offset 1w) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m] offset 1w) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Write Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 35, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval]) or irate(mysql_global_status_questions{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval] offset 1d) or irate(mysql_global_status_questions{alias=\"$host\"}[5m] offset 1d)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval] offset 1w) or irate(mysql_global_status_questions{alias=\"$host\"}[5m] offset 1w)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Questions", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 34, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval] offset 1d) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m] offset 1d)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }} 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval] offset 1w) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m] offset 1w)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }} 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Rows Read", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 36, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval])) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval] offset 1d)) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m] offset 1d))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval] offset 1w)) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m] offset 1w))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Rows Changed", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "MySQL Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Trends Dashboard | Percona App", - "version": 1 - } - nodes.json: |- - { - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "Dashboard to get an overview of one server", - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "100 - (avg by (cpu) (irate(node_cpu{mode=\"idle\", instance=\"$server\"}[5m])) * 100)", - "hide": false, - "intervalFactor": 10, - "legendFormat": "{{cpu}}", - "refId": "A", - "step": 50 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node_load1{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "node_load5{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "node_load15{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory used", - "metric": "", - "refId": "C", - "step": 10 - }, - { - "expr": "node_memory_Buffers{instance=\"$server\"}", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "", - "refId": "E", - "step": 10 - }, - { - "expr": "node_memory_Cached{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "", - "refId": "F", - "step": 10 - }, - { - "expr": "node_memory_MemFree{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "", - "refId": "D", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "((node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}) / node_memory_MemTotal{instance=\"$server\"}) * 100", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (instance) (rate(node_disk_bytes_read{instance=\"$server\"}[2m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum by (instance) (rate(node_disk_bytes_written{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum by (instance) (rate(node_disk_io_time_ms{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=\"$server\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_receive_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "A", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_transmit_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "B", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "system" - ], - "templating": { - "list": [ - { - "allValue": null, - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "server", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Nodes", - "version": 3 - } - system.json: |- - { - "__inputs": [{ - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - }], - "__requires": [{ - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [{ - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - }, - { - "datasource": "prometheus", - "enable": false, - "expr": "ALERTS{instance=~\"^$host$\", alertstate=\"firing\"}", - "iconColor": "rgb(252, 5, 0)", - "name": "Alert", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{alertstate}}", - "titleFormat": "{{ alertname }}" - }, - { - "datasource": "prometheus", - "enable": true, - "expr": "ALERTS{instance=~\"^$host$\",alertstate=\"pending\"}", - "iconColor": "rgb(228, 242, 9)", - "name": "Warning", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{ alertstate }}", - "titleFormat": "{{ alertname }}" - } - ] - }, - "description": "Prometheus for system metrics. \r\nLoad, CPU, RAM, network, process ... (mod of https://grafana.com/dashboards/159)", - "editable": true, - "gnetId": 159, - "graphTooltip": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": "30s", - "rows": [{ - "collapse": false, - "height": "250px", - "panels": [{ - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "decimals": 1, - "editable": true, - "error": false, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 19, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "s", - "postfixFontSize": "80%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_time{instance=~\"^$host$\"} - node_boot_time{instance=~\"^$host$\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_time%7Balias%3D%5C%22%24host%5C%22%7D%20-%20node_boot_time%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A25%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "300,3600", - "title": "System Uptime", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 25, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "count(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300 - }], - "thresholds": "", - "title": "Virtual CPUs", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 26, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "sum(node_memory_MemAvailable{instance=~\"^$host$\"})", - "interval": "", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_memory_MemAvailable", - "refId": "A", - "step": 30 - }], - "thresholds": "", - "title": "RAM available", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "decimals": 0, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(sum(node_memory_MemAvailable{instance=~\"^$host$\"}) or (sum(node_memory_MemFree{instance=~\"^$host$\"}) + sum(node_memory_Buffers{instance=~\"^$host$\"}) + sum(node_memory_Cached{instance=~\"^$host$\"}))) / sum(node_memory_MemTotal{instance=~\"^$host$\"}) * 100", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_mem", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%20%2F%20node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20*%20100%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-15%2013%3A54%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "90,95", - "title": "Memory Available", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "prometheus", - "decimals": null, - "editable": true, - "error": false, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=~\"^$host$\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"})", - "format": "time_series", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300, - "target": "" - }], - "thresholds": "75,95", - "title": "Disk space usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "260px", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{instance=~\"^$host$\"}[$interval])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"}) or sum(irate(node_cpu{instance=~\"^$host$\"}[5m])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "{{ mode }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2 - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Load 1m", - "color": "#E24D42" - }, - { - "alias": "Load 5m", - "color": "#E0752D" - }, - { - "alias": "Load 15m", - "color": "#E5AC0E" - } - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load1{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 1m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load5{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 5m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load5%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load15{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 15m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load15%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 2, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 6, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#0A437C" - }, - { - "alias": "Available", - "color": "#5195CE" - }, - { - "alias": "Total", - "color": "#052B51", - "legend": false, - "stack": false - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Total", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"}))", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Available", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 29, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Buffers{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Buffers", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Cached{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Distribution", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 24, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Forks", - "color": "#EF843C" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_forks{instance=~\"^$host$\"}[$interval]) or irate(node_forks{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Forks", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Forks", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Processes blocked waiting for I/O to complete", - "color": "#E24D42" - }, - { - "alias": "Processes in runnable state", - "color": "#6ED0E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_running{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes in runnable state", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_blocked{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes blocked waiting for I/O to complete", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_blocked%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Processes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 27, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_context_switches{instance=~\"^$host$\"}[$interval]) or irate(node_context_switches{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Context Switches", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Context Switches", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Interrupts", - "color": "#D683CE" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_intr{instance=~\"^$host$\"}[$interval]) or irate(node_intr{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Interrupts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Interrupts", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Inbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Outbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sort": "min", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600, - "target": "" - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Network Utilization Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#584477" - }, - { - "alias": "Free", - "color": "#AEA2E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapTotal{instance=~\"^$host$\"} - node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 30, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpin{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpin{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpout{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpout{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "prometheus", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "system" - ], - "templating": { - "list": [{ - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "5s", - "value": "5s" - }, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [{ - "selected": false, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": true, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": ".+", - "current": {}, - "datasource": "prometheus", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 2, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "instance", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "System", - "version": 0 - } diff --git a/charts-values/prometheus/values.yaml b/charts-values/prometheus/values.yaml deleted file mode 100644 index ed5048637..000000000 --- a/charts-values/prometheus/values.yaml +++ /dev/null @@ -1,19 +0,0 @@ -rbac: - create: true - -openshift: true - -alertmanager: - enabled: false - -pushgateway: - enabled: false - -server: - ingress: - hosts: - - prometheus.lagoon.vicsdp.amazee.io - -nodeExporter: - nodeSelector: - region: node \ No newline at end of file diff --git a/charts/clair/.helmignore b/charts/clair/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/charts/clair/.helmignore +++ /dev/null @@ -1,21 +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 -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/charts/clair/Chart.yaml b/charts/clair/Chart.yaml deleted file mode 100644 index ba3bdd787..000000000 --- a/charts/clair/Chart.yaml +++ /dev/null @@ -1,11 +0,0 @@ -name: clair -home: https://coreos.com/clair -version: 0.1.0 -appVersion: 3.0.0-pre -description: Clair is an open source project for the static analysis of vulnerabilities in application containers. -icon: https://cloud.githubusercontent.com/assets/343539/21630811/c5081e5c-d202-11e6-92eb-919d5999c77a.png -sources: - - https://github.com/coreos/clair -maintainers: - - name: Jimmy Zelinskie - - email: jimmy.zelinskie@coreos.com diff --git a/charts/clair/requirements.yaml b/charts/clair/requirements.yaml deleted file mode 100644 index ef1fd2cc4..000000000 --- a/charts/clair/requirements.yaml +++ /dev/null @@ -1,5 +0,0 @@ -dependencies: - - name: postgresql - version: "*" - condition: postgresql.enabled - repository: "alias:stable" \ No newline at end of file diff --git a/charts/clair/templates/_helpers.tpl b/charts/clair/templates/_helpers.tpl deleted file mode 100644 index e91cc6b67..000000000 --- a/charts/clair/templates/_helpers.tpl +++ /dev/null @@ -1,23 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -Create a default fully qualified postgresql name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "postgresql.fullname" -}} -{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/charts/clair/templates/configmap.yaml b/charts/clair/templates/configmap.yaml deleted file mode 100644 index e30cab3e4..000000000 --- a/charts/clair/templates/configmap.yaml +++ /dev/null @@ -1,92 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ template "fullname" . }} - labels: - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" -data: - config.yaml: | - clair: - database: - # Database driver - type: pgsql - options: - # PostgreSQL Connection string - # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING - # This should be done using secrets or Vault, but for now this will also work - {{- if .Values.config.postgresURI -}} - source: "{{ .Values.config.postgresURI }}" - {{ else }} - source: "postgres://{{ .Values.postgresql.postgresUser }}:{{ .Values.postgresql.postgresPassword }}@{{ template "postgresql.fullname" . }}:5432/{{ .Values.postgresql.postgresDatabase }}?sslmode=disable" - {{ end }} - - # Number of elements kept in the cache - # Values unlikely to change (e.g. namespaces) are cached in order to save prevent needless roundtrips to the database. - cachesize: 16384 - - # 32-bit URL-safe base64 key used to encrypt pagination tokens - # If one is not provided, it will be generated. - # Multiple clair instances in the same cluster need the same value. - paginationkey: "{{ .Values.config.paginationKey }}" - api: - # v3 grpc/RESTful API server address - addr: "0.0.0.0:6060" - - # Health server address - # This is an unencrypted endpoint useful for load balancers to check to healthiness of the clair server. - healthaddr: "0.0.0.0:6061" - - # Deadline before an API request will respond with a 503 - timeout: 900s - - # Optional PKI configuration - # If you want to easily generate client certificates and CAs, try the following projects: - # https://github.com/coreos/etcd-ca - # https://github.com/cloudflare/cfssl - servername: - cafile: - keyfile: - certfile: - - worker: - namespace_detectors: - {{- range $key, $value := .Values.config.enabledNamespaceDetectors }} - - {{ $value }} - {{- end }} - - feature_listers: - {{- range $key, $value := .Values.config.enabledFeatureListers }} - - {{ $value }} - {{- end }} - - updater: - # Frequency the database will be updated with vulnerabilities from the default data sources - # The value 0 disables the updater entirely. - interval: "{{ .Values.config.updateInterval }}" - enabledupdaters: - {{- range $key, $value := .Values.config.enabledUpdaters }} - - {{ $value }} - {{- end }} - - notifier: - # Number of attempts before the notification is marked as failed to be sent - attempts: 3 - - # Duration before a failed notification is retried - renotifyinterval: 2h - - http: - # Optional endpoint that will receive notifications via POST requests - endpoint: "{{ .Values.config.notificationWebhookEndpoint }}" - - # Optional PKI configuration - # If you want to easily generate client certificates and CAs, try the following projects: - # https://github.com/cloudflare/cfssl - # https://github.com/coreos/etcd-ca - servername: - cafile: - keyfile: - certfile: - - # Optional HTTP Proxy: must be a valid URL (including the scheme). - proxy: diff --git a/charts/clair/templates/deployment.yaml b/charts/clair/templates/deployment.yaml deleted file mode 100644 index 561bb0f9f..000000000 --- a/charts/clair/templates/deployment.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: {{ template "fullname" . }} - labels: - hertiage: {{ .Release.Service | quote }} - release: {{ .Release.Name | quote }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" - component: {{ .Release.Name }} -spec: - replicas: {{ .Values.replicaCount }} - template: - metadata: - labels: - app: {{ template "fullname" . }} - spec: - volumes: - - name: "{{ .Chart.Name }}-config" - configMap: - name: {{ template "fullname" . }} - containers: - - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} - args: - - "-log-level={{ .Values.logLevel }}" - {{ if .Values.insecureTls }}- "--insecure-tls" {{end}} - ports: - - name: clair-api - containerPort: {{ .Values.service.internalApiPort }} - protocol: TCP - - name: clair-health - containerPort: {{ .Values.service.internalHealthPort }} - protocol: TCP - livenessProbe: - httpGet: - path: /health - port: {{ .Values.service.internalHealthPort }} - readinessProbe: - httpGet: - path: /health - port: {{ .Values.service.internalHealthPort }} - volumeMounts: - - name: "{{ .Chart.Name }}-config" - mountPath: /etc/clair - resources: -{{ toYaml .Values.resources | indent 10 }} diff --git a/charts/clair/templates/ingress.yaml b/charts/clair/templates/ingress.yaml deleted file mode 100644 index 7b1c5cdd5..000000000 --- a/charts/clair/templates/ingress.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.ingress.enabled -}} -{{- $serviceName := include "fullname" . -}} -{{- $servicePort := .Values.service.externalApiPort -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: {{ template "fullname" . }} - labels: - app: {{ template "fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" - annotations: - {{- range $key, $value := .Values.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} -spec: - rules: - {{- range $host := .Values.ingress.hosts }} - - host: {{ $host }} - http: - paths: - - path: / - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- if .Values.ingress.tls }} - tls: -{{ toYaml .Values.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/charts/clair/templates/service.yaml b/charts/clair/templates/service.yaml deleted file mode 100644 index 1f9d26e48..000000000 --- a/charts/clair/templates/service.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: {{ template "fullname" . }} - labels: - chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" -spec: - type: {{ .Values.service.type }} - ports: - - name: clair-api - port: {{ .Values.service.externalApiPort }} - targetPort: {{ .Values.service.internalApiPort }} - protocol: TCP - name: "{{ .Values.service.name }}-api" - - name: clair-health - port: {{ .Values.service.externalHealthPort }} - targetPort: {{ .Values.service.internalHealthPort }} - protocol: TCP - name: "{{ .Values.service.name }}-health" - selector: - app: {{ template "fullname" . }} diff --git a/charts/clair/values.yaml b/charts/clair/values.yaml deleted file mode 100644 index a30b8dcb8..000000000 --- a/charts/clair/values.yaml +++ /dev/null @@ -1,71 +0,0 @@ -# Default values for clair. -# This is a YAML-formatted file. -# Declare variables to be passed into your templates. -replicaCount: 1 -logLevel: info -insecureTls: false -image: - repository: quay.io/coreos/clair-git - tag: latest - pullPolicy: Always -service: - name: clair - type: ClusterIP - internalApiPort: 6060 - externalApiPort: 6060 - internalHealthPort: 6061 - externalHealthPort: 6061 -ingress: - enabled: false - # Used to create Ingress record (should used with service.type: ClusterIP). - hosts: - - chart-example.local - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - tls: - # Secrets must be manually created in the namespace. - # - secretName: chart-example-tls - # hosts: - # - chart-example.local -resources: - limits: - cpu: 100m - memory: 1Gi - requests: - cpu: 100m - memory: 128Mi -config: - # postgresURI: "postgres://user:password@host:5432/postgres?sslmode=disable" - paginationKey: "XxoPtCUzrUv4JV5dS+yQ+MdW7yLEJnRMwigVY/bpgtQ=" - updateInterval: 2h - notificationWebhookEndpoint: https://example.com/notify/me - enabledUpdaters: - - debian - - ubuntu - - rhel - - oracle - - alpine - enabledNamespaceDetectors: - - os-release - - lsb-release - - apt-sources - - alpine-release - - redhat-release - enabledFeatureListers: - - apk - - dpkg - - rpm -# Configuration values for the postgresql dependency. -# ref: https://github.com/kubernetes/charts/blob/master/stable/postgresql/README.md -postgresql: - cpu: 1000m - memory: 1Gi -# These values are hardcoded until Helm supports secrets. -# For more info see: https://github.com/kubernetes/helm/issues/2196 - postgresUser: clair - postgresPassword: clair - postgresDatabase: clair - - persistence: - size: 10Gi \ No newline at end of file diff --git a/charts/grafana-dpc/Chart.yaml b/charts/grafana-dpc/Chart.yaml deleted file mode 100755 index c61b3275f..000000000 --- a/charts/grafana-dpc/Chart.yaml +++ /dev/null @@ -1,11 +0,0 @@ -description: The leading tool for querying and visualizing time series and metrics. -engine: gotpl -home: https://grafana.net -icon: https://raw.githubusercontent.com/grafana/grafana/master/public/img/logo_transparent_400x.png -maintainers: -- email: zanhsieh@gmail.com - name: Ming Hsieh -name: grafana-dpc -sources: -- https://github.com/grafana/grafana -version: 0.5.0 diff --git a/charts/grafana-dpc/README.md b/charts/grafana-dpc/README.md deleted file mode 100755 index 83a705eab..000000000 --- a/charts/grafana-dpc/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# Grafana Helm Chart - -* Installs the web dashboarding system [Grafana](http://grafana.org/) - -## TL;DR; - -```console -$ helm install stable/grafana -``` - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm install --name my-release stable/grafana -``` - -## Uninstalling the Chart - -To uninstall/delete the my-release deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - - -## Configuration - -| Parameter | Description | Default | -|-------------------------------------------|-------------------------------------|---------------------------------------------------| -| `server.image` | Container image to run | grafana/grafana:latest | -| `server.adminUser` | Admin user username | admin | -| `server.adminPassword` | Admin user password | Randomly generated | -| `server.persistentVolume.enabled` | Create a volume to store data | true | -| `server.persistentVolume.size` | Size of persistent volume claim | 1Gi RW | -| `server.persistentVolume.storageClass` | Type of persistent volume claim | `nil` (uses alpha storage class annotation) | -| `server.persistentVolume.accessMode` | ReadWriteOnce or ReadOnly | [ReadWriteOnce] | -| `server.persistentVolume.existingClaim` | Existing persistent volume claim | null | -| `server.persistentVolume.subPath` | Subdirectory of pvc to mount | null | -| `server.resources` | Server resource requests and limits | requests: {cpu: 100m, memory: 100Mi} | -| `server.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | null | -| `server.service.annotations` | Service annotations | null | -| `server.service.httpPort` | Service port | 80 | -| `server.service.loadBalancerIP` | IP to assign to load balancer | null | -| `server.service.loadBalancerSourceRanges` | List of IP CIDRs allowed access | null | -| `server.service.nodePort` | For service type "NodePort" | null | -| `server.service.type` | ClusterIP, NodePort, or LoadBalancer| ClusterIP | -| `server.setDatasource.enabled` | Creates grafana datasource with job | false | diff --git a/charts/grafana-dpc/templates/NOTES.txt b/charts/grafana-dpc/templates/NOTES.txt deleted file mode 100755 index 8d84fbc5b..000000000 --- a/charts/grafana-dpc/templates/NOTES.txt +++ /dev/null @@ -1,38 +0,0 @@ -1. Get your '{{ .Values.server.adminUser }}' user password by running: - - kubectl get secret --namespace {{ .Release.Namespace }} {{ template "grafana.server.fullname" . }} -o jsonpath="{.data.grafana-admin-password}" | base64 --decode ; echo - -2. The Grafana server can be accessed via port {{ .Values.server.service.httpPort }} on the following DNS name from within your cluster: - - {{ template "grafana.server.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local -{{ if .Values.server.ingress.enabled }} - From outside the cluster, the server URL(s) are: -{{- range .Values.server.ingress.hosts }} - http://{{ . }} -{{- end }} -{{ else }} - Get the Grafana URL to visit by running these commands in the same shell: -{{ if contains "NodePort" .Values.server.service.type -}} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "grafana.server.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{ else if contains "LoadBalancer" .Values.server.service.type -}} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "grafana.server.fullname" . }}' - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "grafana.server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.server.httpPort -}} -{{ else if contains "ClusterIP" .Values.server.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "grafana.fullname" . }},component={{ .Values.server.name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 3000 -{{- end }} -{{- end }} - -3. Login with the password from step 1 and the username: {{ .Values.server.adminUser }} - -{{- if .Values.server.persistentVolume.enabled }} -{{- else }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the Grafana pod is terminated. ##### -################################################################################# -{{- end }} diff --git a/charts/grafana-dpc/templates/_helpers.tpl b/charts/grafana-dpc/templates/_helpers.tpl deleted file mode 100755 index 11f5ffe08..000000000 --- a/charts/grafana-dpc/templates/_helpers.tpl +++ /dev/null @@ -1,24 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "grafana.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "grafana.fullname" -}} -{{- $name := default "grafana" .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified server name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "grafana.server.fullname" -}} -{{- printf "%s-%s" .Release.Name "grafana" | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/charts/grafana-dpc/templates/configmap.yaml b/charts/grafana-dpc/templates/configmap.yaml deleted file mode 100755 index 3bb71dae4..000000000 --- a/charts/grafana-dpc/templates/configmap.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }}-config -data: - {{- if .Values.server.installPlugins }} - grafana-install-plugins: {{ .Values.server.installPlugins | quote }} - {{- end }} -{{ toYaml .Values.serverConfigFile | indent 2 }} diff --git a/charts/grafana-dpc/templates/dashboards-configmap.yaml b/charts/grafana-dpc/templates/dashboards-configmap.yaml deleted file mode 100755 index 67851f208..000000000 --- a/charts/grafana-dpc/templates/dashboards-configmap.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }}-dashs -data: -{{ toYaml .Values.serverDashboardFiles | indent 2 }} diff --git a/charts/grafana-dpc/templates/deployment.yaml b/charts/grafana-dpc/templates/deployment.yaml deleted file mode 100755 index 1064c607a..000000000 --- a/charts/grafana-dpc/templates/deployment.yaml +++ /dev/null @@ -1,118 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -spec: - replicas: 1 - template: - metadata: - annotations: - checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} - checksum/dashboards-config: {{ include (print $.Template.BasePath "/dashboards-configmap.yaml") . | sha256sum }} - {{- range $key, $value := .Values.server.annotations }} - {{ $key }}: {{ $value }} - {{- end }} - labels: - app: {{ template "grafana.fullname" . }} - component: "{{ .Values.server.name }}" - release: "{{ .Release.Name }}" - spec: - nodeSelector: -{{ toYaml .Values.server.nodeSelector | indent 8 }} - {{- if .Values.server.tolerations }} - tolerations: -{{ toYaml .Values.server.tolerations | indent 8 }} - {{- end }} - containers: - - name: {{ template "grafana.name" . }} - image: "{{ .Values.server.image }}" - imagePullPolicy: {{ default "Always" .Values.server.imagePullPolicy }} - env: - - name: GF_SECURITY_ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-user - - name: GF_SECURITY_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-password - {{- if .Values.server.installPlugins }} - - name: GF_INSTALL_PLUGINS - valueFrom: - configMapKeyRef: - name: {{ template "grafana.server.fullname" . }}-config - key: grafana-install-plugins - {{- end }} - {{- if .Values.server.setGenericOauth.enabled }} - - name: GF_AUTH_GENERIC_OAUTH_ENABLED - value: "true" - - name: GF_AUTH_GENERIC_OAUTH_CLIENT_ID - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }}-oauth - key: client-id - - name: GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }}-oauth - key: client-secret - - name: GF_AUTH_GENERIC_OAUTH_SCOPES - value: {{ .Values.server.setGenericOauth.scopes | quote }} - - name: GF_AUTH_GENERIC_OAUTH_AUTH_URL - value: {{ .Values.server.setGenericOauth.authUrl | quote }} - - name: GF_AUTH_GENERIC_OAUTH_TOKEN_URL - value: {{ .Values.server.setGenericOauth.tokenUrl | quote }} - - name: GF_AUTH_GENERIC_OAUTH_API_URL - value: {{ .Values.server.setGenericOauth.apiUrl | quote }} - # TODO: What about allowedDomains? - - name: GF_AUTH_GENERIC_OAUTH_ALLOWSIGNUP - value: {{ .Values.server.setGenericOauth.allowSignUp | quote }} - {{- end }} - # The following values are so that Oauth works correctly. - # But they can be used for other reasons as well. - # TODO: Might need to put a check that the value exists? - - name: GF_SERVER_DOMAIN - value: {{ .Values.server.serverDomain | quote }} - - name: GF_SERVER_ROOT_URL - value: {{ .Values.server.serverRootUrl | quote }} - ports: - - containerPort: 3000 - readinessProbe: - httpGet: - path: /login - port: 3000 - initialDelaySeconds: 30 - timeoutSeconds: 30 - resources: -{{ toYaml .Values.server.resources | indent 12 }} - volumeMounts: - - name: config-volume - mountPath: {{ default "/etc/grafana" .Values.server.configLocalPath | quote }} - - name: dashboard-volume - mountPath: {{ default "/var/lib/grafana/dashboards" .Values.server.dashboardLocalPath | quote }} - - name: storage-volume - mountPath: {{ default "/var/lib/grafana" .Values.server.storageLocalPath | quote }} - subPath: "{{ .Values.server.persistentVolume.subPath }}" - terminationGracePeriodSeconds: {{ default 300 .Values.server.terminationGracePeriodSeconds }} - volumes: - - name: config-volume - configMap: - name: {{ template "grafana.server.fullname" . }}-config - - name: dashboard-volume - configMap: - name: {{ template "grafana.server.fullname" . }}-dashs - - name: storage-volume - {{- if .Values.server.persistentVolume.enabled }} - persistentVolumeClaim: - claimName: {{ if .Values.server.persistentVolume.existingClaim }}{{ .Values.server.persistentVolume.existingClaim }}{{- else }}{{ template "grafana.server.fullname" . }}{{- end }} - {{- else }} - emptyDir: {} - {{- end -}} diff --git a/charts/grafana-dpc/templates/ingress.yaml b/charts/grafana-dpc/templates/ingress.yaml deleted file mode 100755 index b3fb83c6c..000000000 --- a/charts/grafana-dpc/templates/ingress.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if .Values.server.ingress.enabled -}} -{{- $releaseName := .Release.Name -}} -{{- $servicePort := .Values.server.service.httpPort -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - annotations: - {{- range $key, $value := .Values.server.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -spec: - rules: - {{- range .Values.server.ingress.hosts }} - - host: {{ . }} - http: - paths: - - backend: - serviceName: {{ printf "%s-%s" $releaseName "grafana" | trunc 63 }} - servicePort: {{ $servicePort }} - {{- end -}} - {{- if .Values.server.ingress.tls }} - tls: -{{ toYaml .Values.server.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/charts/grafana-dpc/templates/job-notify.yaml b/charts/grafana-dpc/templates/job-notify.yaml deleted file mode 100644 index 0a48f1f8b..000000000 --- a/charts/grafana-dpc/templates/job-notify.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if .Values.server.setNotificationChannel.enabled -}} -apiVersion: batch/v1 -kind: Job -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }}-set-notification-channel -spec: - activeDeadlineSeconds: {{ default 300 .Values.server.setDatasource.activeDeadlineSeconds }} - template: - metadata: - labels: - app: {{ template "grafana.fullname" . }} - component: "{{ .Values.server.name }}" - release: "{{ .Release.Name }}" - spec: - containers: - - name: {{ template "grafana.server.fullname" . }}-set-notification-channel - image: "{{ .Values.server.setNotificationChannel.image }}" - env: - - name: ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-user - - name: ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-password - args: - - "http://$(ADMIN_USER):$(ADMIN_PASSWORD)@{{ template "grafana.fullname" . }}:{{ .Values.server.httpPort }}/api/alert-notifications" - - "--max-time" - - "10" - - "-H" - - "Content-Type: application/json;charset=UTF-8" - - "-d" - {{- with .Values.server.setNotificationChannel.channel }} - - '{"name": "{{ .name }}", - "type": "{{ .type }}", - "settings": { "url": "{{ .url }}" }, - "isDefault": {{ .isDefault | default "null" }} }' - {{- end }} - restartPolicy: {{ .Values.server.setNotificationChannel.restartPolicy }} -{{- end -}} diff --git a/charts/grafana-dpc/templates/job.yaml b/charts/grafana-dpc/templates/job.yaml deleted file mode 100755 index 838f48347..000000000 --- a/charts/grafana-dpc/templates/job.yaml +++ /dev/null @@ -1,53 +0,0 @@ -{{- if .Values.server.setDatasource.enabled -}} -apiVersion: batch/v1 -kind: Job -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }}-set-datasource -spec: - activeDeadlineSeconds: {{ default 300 .Values.server.setDatasource.activeDeadlineSeconds }} - template: - metadata: - labels: - app: {{ template "grafana.fullname" . }} - component: "{{ .Values.server.name }}" - release: "{{ .Release.Name }}" - spec: - containers: - - name: {{ template "grafana.server.fullname" . }}-set-datasource - image: "{{ .Values.server.setDatasource.image }}" - env: - - name: ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-user - - name: ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }} - key: grafana-admin-password - args: - - "http://$(ADMIN_USER):$(ADMIN_PASSWORD)@{{ template "grafana.fullname" . }}:{{ .Values.server.httpPort }}/api/datasources" - - "--max-time" - - "10" - - "-H" - - "Content-Type: application/json;charset=UTF-8" - - "-d" - {{- with .Values.server.setDatasource.datasource }} - - '{"name": "{{ .name }}", - "type": "{{ .type }}", - "url": "{{ .url }}", - "access": "{{ .access | default "proxy" }}", - "basicAuth": false, - "database": {{ .database | default "null" }}, - "jsonData": {{ .jsonData | default "null" }}, - "isDefault": {{ .isDefault | default "null" }} }' - {{- end }} - restartPolicy: {{ .Values.server.setDatasource.restartPolicy }} -{{- end -}} diff --git a/charts/grafana-dpc/templates/pvc.yaml b/charts/grafana-dpc/templates/pvc.yaml deleted file mode 100755 index 4c05a3f86..000000000 --- a/charts/grafana-dpc/templates/pvc.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.server.persistentVolume.enabled -}} -{{- if not .Values.server.persistentVolume.existingClaim -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - annotations: - {{- if .Values.server.persistentVolume.annotations }} -{{ toYaml .Values.server.persistentVolume.annotations | indent 4 }} - {{- end }} - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -spec: - accessModes: -{{- range .Values.server.persistentVolume.accessModes }} - - {{ . | quote }} -{{- end }} - resources: - requests: - storage: {{ .Values.server.persistentVolume.size | quote }} -{{- if .Values.server.persistentVolume.storageClass }} -{{- if (eq "-" .Values.server.persistentVolume.storageClass) }} - storageClassName: "" -{{- else }} - storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" -{{- end }} -{{- end }} -{{- end -}} -{{- end -}} diff --git a/charts/grafana-dpc/templates/route.yaml b/charts/grafana-dpc/templates/route.yaml deleted file mode 100644 index df741e1db..000000000 --- a/charts/grafana-dpc/templates/route.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.openshift -}} -{{- $releaseName := .Release.Name -}} -{{- $servicePort := .Values.server.service.httpPort -}} -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - annotations: - {{- range $key, $value := .Values.server.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -spec: - host: {{ .Values.server.ingress.hosts | first }} - to: - kind: Service - name: {{ printf "%s-%s" $releaseName "grafana" | trunc 63 }} - weight: 100 - wildcardPolicy: None -{{- end -}} diff --git a/charts/grafana-dpc/templates/secret-oauth.yaml b/charts/grafana-dpc/templates/secret-oauth.yaml deleted file mode 100644 index 8f87ac0c4..000000000 --- a/charts/grafana-dpc/templates/secret-oauth.yaml +++ /dev/null @@ -1,15 +0,0 @@ -{{- if .Values.server.setGenericOauth.enabled -}} -apiVersion: v1 -kind: Secret -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }}-oauth -type: Opaque -data: - client-id: {{ .Values.server.setGenericOauth.clientId | b64enc | quote }} - client-secret: {{ .Values.server.setGenericOauth.clientSecret | b64enc | quote }} -{{- end -}} \ No newline at end of file diff --git a/charts/grafana-dpc/templates/secret.yaml b/charts/grafana-dpc/templates/secret.yaml deleted file mode 100755 index 3e8e9d013..000000000 --- a/charts/grafana-dpc/templates/secret.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -type: Opaque -data: - {{- if .Values.server.adminPassword }} - grafana-admin-password: {{ .Values.server.adminPassword | b64enc | quote }} - {{- else }} - grafana-admin-password: {{ randAlphaNum 10 | b64enc | quote }} - {{- end }} - grafana-admin-user: {{ .Values.server.adminUser | b64enc | quote }} diff --git a/charts/grafana-dpc/templates/svc.yaml b/charts/grafana-dpc/templates/svc.yaml deleted file mode 100755 index ab1934f4a..000000000 --- a/charts/grafana-dpc/templates/svc.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.server.service.annotations }} - annotations: -{{ toYaml .Values.server.service.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "grafana.fullname" . }} - chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" - component: "{{ .Values.server.name }}" - heritage: "{{ .Release.Service }}" - release: "{{ .Release.Name }}" - name: {{ template "grafana.server.fullname" . }} -spec: - ports: - - name: {{ default "http" .Values.server.service.httpPortName | quote }} - port: {{ .Values.server.service.httpPort }} - protocol: TCP - targetPort: 3000 -{{- if contains "NodePort" .Values.server.service.type }} - {{- if .Values.server.service.nodePort }} - nodePort: {{ .Values.server.service.nodePort }} - {{- end }} -{{- end }} - selector: - app: {{ template "grafana.fullname" . }} - component: "{{ .Values.server.name }}" - type: "{{ .Values.server.service.type }}" -{{- if contains "LoadBalancer" .Values.server.service.type }} - {{- if .Values.server.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} - {{- end -}} - {{- if .Values.server.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range .Values.server.service.loadBalancerSourceRanges }} - - {{ . }} - {{- end }} - {{- end -}} -{{- end -}} diff --git a/charts/grafana-dpc/values.yaml b/charts/grafana-dpc/values.yaml deleted file mode 100755 index fb2efc582..000000000 --- a/charts/grafana-dpc/values.yaml +++ /dev/null @@ -1,421 +0,0 @@ -openshift: false - -server: - - # This is an extension of the standard Helm Chart - setNotificationChannel: - enabled: true - image: appropriate/curl:latest - restartPolicy: OnFailure - channel: - name: "salsa_dpc #bay-build" - type: slack - url: "https://hooks.slack.com/services/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" - isDefault: true - - # This is an extension of the standard Helm Chart - setGenericOauth: - enabled: false - clientId: XXXXXXXXXXXX - clientSecret: YYYYYYYYYYYY - scopes: email user_data - authUrl: https://citopro.au.auth0.com/authorize - tokenUrl: https://citopro.au.auth0.com/oauth/token - apiUrl: https://citopro.au.auth0.com/userinfo - #allowedDomains: mycompany.com mycompany.org - allowSignUp: true - - # This is an extension of the standard Helm Chart - serverDomain: e947ef49.ngrok.io - serverRootUrl: "%(protocol)s://%(domain)s/" - - - - ## Grafana Pod annotations: - ## - # annotations: - # iam.amazonaws.com/role: grafana - - ## Grafana Docker image - ## - image: "grafana/grafana:latest" - - nodeSelector: {} - tolerations: [] - - ingress: - ## If true, Grafana Ingress will be created - ## - enabled: false - - ## Grafana Ingress annotations - ## - # annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: 'true' - - ## Grafana Ingress hostnames - ## Must be provided if Ingress is enabled - ## - # hosts: - # - grafana.domain.com - - ## Grafana Ingress TLS configuration - ## Secrets must be manually created in the namespace - ## - # tls: - # - secretName: grafana-server-tls - # hosts: - # - grafana.domain.com - - ## Grafana container name - ## - name: grafana - - adminUser: "admin" - # adminPassword: "admin" - - ## Global imagePullPolicy - ## Default: 'Always' if image tag is 'latest', else 'IfNotPresent' - ## Ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images - ## - # imagePullPolicy: - - # Persist data to a persitent volume - persistentVolume: - ## If true, Grafana will create a Persistent Volume Claim - ## If false, use emptyDir - ## - enabled: true - - ## Grafana data Persistent Volume access modes - ## Must match those of existing PV or dynamic provisioner - ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - accessModes: - - ReadWriteOnce - - ## Grafana data Persistent Volume annotations - ## - annotations: {} - - ## Grafana data Persistent Volume existing claim name - ## Requires server.persistentVolume.enabled: true - ## If defined, PVC must be created manually before volume will be bound - existingClaim: "" - - ## Grafana data Persistent Volume size - ## Default: 1Gi - ## - size: 1Gi - - ## grafana data Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - ## Subdirectory of data Persistent Volume to mount - ## Useful if the volume's root directory is not empty - ## - subPath: "" - - ## Grafana resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: - # limits: - # cpu: 500m - # memory: 512Mi - requests: - cpu: 100m - memory: 100Mi - - ## Grafana service - service: - ## Grafana service annotations - ## - annotations: {} - - ## Grafana service type - ## - type: ClusterIP - - ## Grafana service port - ## - httpPort: 80 - - ## Load balancer IP address - ## Is not required, but allows for static address with - ## serviceType LoadBalancer. - ## If not supported by cloud provider, this field is ignored. - ## Default: nil - ## - # loadBalancerIP: 130.211.x.x - - ## This will restrict traffic through the cloud-provider load-balancer - ## to the specified client IPs. - ## If not supported by cloud provider, this field is ignored. - ## Default: nil - ## - # loadBalancerSourceRanges: - # - 0.0.0.0/0 - - ## nodePort port number - ## Is not required, but allows for static port assignment with - ## serviceType NodePort. - ## Default: nil - # nodePort: 30000 - - ## Grafana local config path - ## Default '/etc/grafana' - ## - # configLocalPath: /etc/grafana - - ## Grafana local dashboards path - ## Default: '/var/lib/grafana/dashboards' - ## - # dashboardLocalPath: /var/lib/grafana/dashboards - - ## Grafana local data storage path - ## Default: '/var/lib/grafana/data' - ## - # storageLocalPath: /var/lib/grafana/data - - ## Grafana Pod termination grace period - ## Default: 300s (5m) - ## - # terminationGracePeriodSeconds: 300 - - ## Pass the plugins you want installed as a comma seperated list. - ## This will pass each plugin name to `grafana-cli plugins install ${plugin}`. - ## Ref: https://github.com/grafana/grafana-docker#installing-plugins-for-grafana-3 - ## - # installPlugins: - - # Set datasource in beginning - setDatasource: - ## If true, an initial Grafana Datasource will be set - ## Default: false - ## - enabled: false - - ## How long should it take to commit failure - ## Default: 300 - ## - # activeDeadlineSeconds: 300 - - ## Curl Docker image - ## Default: appropriate/curl:latest - ## - # image: appropriate/curl:latest - - ## This assembles how curl post into Grafana - ## Ref1: http://docs.grafana.org/reference/http_api/#create-data-source - ## Ref2: https://github.com/grafana/grafana/issues/1789 - ## - # datasource: - ## The datasource name. - ## Default: default - # name: default - - ## Type of datasource - ## Default: prometheus - ## - # type: prometheus - - ## The url of the datasource. To set correctly you need to know - ## the right datasource name and its port ahead. Check kubernetes - ## dashboard or describe the service should fulfill the requirements. - ## Synatx like `http://-: - ## Default: "http://limping-tiger-server" - ## - # url: "http://limping-tiger-server" - - ## The name of the database at the datasource. - ## Required parameter when used with elasticsearch, which refers to the index_name - ## Default: - # database: - - ## Additional JSON data to be passed to the configuration of the datasource. - ## The JSON data is passed to curl, therefore it needs proper quoting and - ## escaping and needs to be on a single line. For example: - ## '\"esVersion\": 2, \"interval\": \"Daily\", \"timeField\": \"@timestamp\"' - # jsonData: null - - ## Specify if Grafana has to go thru proxy to reach datasource - ## Default: proxy - ## - # access: proxy - - ## Specify should Grafana use this datasource as default - ## Default: true - ## - # isDefault: true - - ## Specify the job policy - ## Default: OnFailure - ## - # restartPolicy: OnFailure - -## Grafana config file ConfigMap entry -## -serverConfigFile: - grafana.ini: | - ; instance_name = ${HOSTNAME} - [paths] - data = /var/lib/grafana/data - logs = /var/log/grafana - plugins = /var/lib/grafana/plugins - - [server] - ;protocol = http - ;http_addr = - ;http_port = 3000 - ;domain = localhost - ;enforce_domain = false - ;root_url = %(protocol)s://%(domain)s:%(http_port)s/ - ;router_logging = false - ;static_root_path = public - ;enable_gzip = false - ;cert_file = - ;cert_key = - - [database] - ;type = sqlite3 - ;host = 127.0.0.1:3306 - ;name = grafana - ;user = root - ;password = - ;ssl_mode = disable - ;path = grafana.db - - [session] - ;provider = file - ;provider_config = sessions - ;cookie_name = grafana_sess - ;cookie_secure = false - ;session_life_time = 86400 - - [analytics] - ;reporting_enabled = true - check_for_updates = true - ;google_analytics_ua_id = - - [security] - ;admin_user = admin - ;admin_password = admin - ;secret_key = SW2YcwTIb9zpOOhoPsMm - ;login_remember_days = 7 - ;cookie_username = grafana_user - ;cookie_remember_name = grafana_remember - ;disable_gravatar = false - ;data_source_proxy_whitelist = - - [snapshots] - ;external_enabled = true - ;external_snapshot_url = https://snapshots-origin.raintank.io - ;external_snapshot_name = Publish to snapshot.raintank.io - - [users] - ;allow_sign_up = true - ;allow_org_create = true - ;auto_assign_org = true - ;auto_assign_org_role = Viewer - ;login_hint = email or username - ;default_theme = dark - - [auth.anonymous] - ;enabled = false - ;org_name = Main Org. - ;org_role = Viewer - - [auth.github] - ;enabled = false - ;allow_sign_up = false - ;client_id = some_id - ;client_secret = some_secret - ;scopes = user:email,read:org - ;auth_url = https://github.com/login/oauth/authorize - ;token_url = https://github.com/login/oauth/access_token - ;api_url = https://api.github.com/user - ;team_ids = - ;allowed_organizations = - - [auth.google] - ;enabled = false - ;allow_sign_up = false - ;client_id = some_client_id - ;client_secret = some_client_secret - ;scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email - ;auth_url = https://accounts.google.com/o/oauth2/auth - ;token_url = https://accounts.google.com/o/oauth2/token - ;api_url = https://www.googleapis.com/oauth2/v1/userinfo - ;allowed_domains = - - [auth.proxy] - ;enabled = false - ;header_name = X-WEBAUTH-USER - ;header_property = username - ;auto_sign_up = true - - [auth.basic] - ;enabled = true - - [auth.ldap] - ;enabled = false - ;config_file = /etc/grafana/ldap.toml - - [smtp] - ;enabled = false - ;host = localhost:25 - ;user = - ;password = - ;cert_file = - ;key_file = - ;skip_verify = false - ;from_address = admin@grafana.localhost - - [emails] - ;welcome_email_on_sign_up = false - - [log] - mode = console - level = info - - [log.console] - ;level = - ;format = console - - [event_publisher] - ;enabled = false - ;rabbitmq_url = amqp://localhost/ - ;exchange = grafana_events - - [dashboards.json] - enabled = true - path = /var/lib/grafana/dashboards - - [metrics] - ;enabled = true - ;interval_seconds = 10 - - ; [metrics.graphite] - ; address = localhost:2003 - ; prefix = prod.grafana.%(instance_name)s. - - [grafana_net] - url = https://grafana.net - - -## Grafana dashboard files ConfigMap entries -## If you'd like to preinstall prometheus dashboard on the same namespace as example, get it from: -## -## https://grafana.net/dashboards/2 -## -## and add it below. -## -serverDashboardFiles: {} diff --git a/charts/prometheus-dpc/.helmignore b/charts/prometheus-dpc/.helmignore deleted file mode 100755 index f0c131944..000000000 --- a/charts/prometheus-dpc/.helmignore +++ /dev/null @@ -1,21 +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 -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/charts/prometheus-dpc/Chart.yaml b/charts/prometheus-dpc/Chart.yaml deleted file mode 100755 index 63eab1813..000000000 --- a/charts/prometheus-dpc/Chart.yaml +++ /dev/null @@ -1,14 +0,0 @@ -description: Prometheus is a monitoring system and time series database. -engine: gotpl -home: https://prometheus.io/ -icon: https://raw.githubusercontent.com/prometheus/prometheus.github.io/master/assets/prometheus_logo-cb55bb5c346.png -maintainers: -- email: mgoodness@gmail.com - name: mgoodness -name: prometheus-dpc -sources: -- https://github.com/prometheus/alertmanager -- https://github.com/prometheus/prometheus -- https://github.com/prometheus/pushgateway -- https://github.com/kubernetes/kube-state-metrics -version: 4.6.12 diff --git a/charts/prometheus-dpc/README.md b/charts/prometheus-dpc/README.md deleted file mode 100755 index 0799f26b9..000000000 --- a/charts/prometheus-dpc/README.md +++ /dev/null @@ -1,248 +0,0 @@ -# Prometheus - -[Prometheus](https://prometheus.io/), a [Cloud Native Computing Foundation](https://cncf.io/) project, is a systems and service monitoring system. It collects metrics from configured targets at given intervals, evaluates rule expressions, displays the results, and can trigger alerts if some condition is observed to be true. - -## TL;DR; - -```console -$ helm install stable/prometheus -``` - -## Introduction - -This chart bootstraps a [Prometheus](https://prometheus.io/) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. - -## Prerequisites - -- Kubernetes 1.3+ with Beta APIs enabled - -## Installing the Chart - -To install the chart with the release name `my-release`: - -```console -$ helm install --name my-release stable/prometheus -``` - -The command deploys Prometheus on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. - -> **Tip**: List all releases using `helm list` - -## Uninstalling the Chart - -To uninstall/delete the `my-release` deployment: - -```console -$ helm delete my-release -``` - -The command removes all the Kubernetes components associated with the chart and deletes the release. - -## Configuration - -The following tables lists the configurable parameters of the Prometheus chart and their default values. - -Parameter | Description | Default ---------- | ----------- | ------- -`alertmanager.enabled` | If true, create alertmanager | `true` -`alertmanager.name` | alertmanager container name | `alertmanager` -`alertmanager.image.repository` | alertmanager container image repository | `prom/alertmanager` -`alertmanager.image.tag` | alertmanager container image tag | `v0.5.1` -`alertmanager.image.pullPolicy` | alertmanager container image pull policy | `IfNotPresent` -`alertmanager.baseURL` | The prefix slug at which the server can be accessed | `` -`alertmanager.extraArgs` | Additional alertmanager container arguments | `{}` -`alertmanager.configMapOverrideName` | Prometheus alertmanager ConfigMap override where full-name is `{{.Release.Name}}-{{.Values.alertmanager.configMapOverrideName}}` and setting this value will prevent the default alertmanager ConfigMap from being generated | `""` -`alertmanager.ingress.enabled` | If true, alertmanager Ingress will be created | `false` -`alertmanager.ingress.annotations` | alertmanager Ingress annotations | `{}` -`alertmanager.ingress.hosts` | alertmanager Ingress hostnames | `[]` -`alertmanager.ingress.tls` | alertmanager Ingress TLS configuration (YAML) | `[]` -`alertmanager.nodeSelector` | node labels for alertmanager pod assignment | `{}` -`alertmanager.persistentVolume.enabled` | If true, alertmanager will create a Persistent Volume Claim | `true` -`alertmanager.persistentVolume.accessModes` | alertmanager data Persistent Volume access modes | `[ReadWriteOnce]` -`alertmanager.persistentVolume.annotations` | Annotations for alertmanager Persistent Volume Claim` | `{}` -`alertmanager.persistentVolume.existingClaim` | alertmanager data Persistent Volume existing claim name | `""` -`alertmanager.persistentVolume.mountPath` | alertmanager data Persistent Volume mount root path | `/data` -`alertmanager.persistentVolume.size` | alertmanager data Persistent Volume size | `2Gi` -`alertmanager.persistentVolume.storageClass` | alertmanager data Persistent Volume Storage Class | `unset` -`alertmanager.persistentVolume.subPath` | Subdirectory of alertmanager data Persistent Volume to mount | `""` -`alertmanager.podAnnotations` | annotations to be added to alertmanager pods | `{}` -`alertmanager.replicaCount` | desired number of alertmanager pods | `1` -`alertmanager.resources` | alertmanager pod resource requests & limits | `{}` -`alertmanager.serviceAccountName` | service account name for alertmanager to use (ignored if rbac.create=true) | `default` -`alertmanager.service.annotations` | annotations for alertmanager service | `{}` -`alertmanager.service.clusterIP` | internal alertmanager cluster service IP | `""` -`alertmanager.service.externalIPs` | alertmanager service external IP addresses | `[]` -`alertmanager.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` -`alertmanager.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` -`alertmanager.service.servicePort` | alertmanager service port | `80` -`alertmanager.service.type` | type of alertmanager service to create | `ClusterIP` -`alertmanagerFiles` | alertmanager ConfigMap entries | `alertmanager.yml` -`configmapReload.name` | configmap-reload container name | `configmap-reload` -`configmapReload.image.repository` | configmap-reload container image repository | `jimmidyson/configmap-reload` -`configmapReload.image.tag` | configmap-reload container image tag | `v0.1` -`configmapReload.image.pullPolicy` | configmap-reload container image pull policy | `IfNotPresent` -`configmapReload.resources` | configmap-reload pod resource requests & limits | `{}` -`kubeStateMetrics.enabled` | If true, create kube-state-metrics | `true` -`kubeStateMetrics.name` | kube-state-metrics container name | `kube-state-metrics` -`kubeStateMetrics.image.repository` | kube-state-metrics container image repository| `gcr.io/google_containers/kube-state-metrics` -`kubeStateMetrics.image.tag` | kube-state-metrics container image tag | `v0.4.1` -`kubeStateMetrics.image.pullPolicy` | kube-state-metrics container image pull policy | `IfNotPresent` -`kubeStateMetrics.nodeSelector` | node labels for kube-state-metrics pod assignment | `{}` -`kubeStateMetrics.podAnnotations` | annotations to be added to kube-state-metrics pods | `{}` -`kubeStateMetrics.replicaCount` | desired number of kube-state-metrics pods | `1` -`kubeStateMetrics.resources` | kube-state-metrics resource requests and limits (YAML) | `{}` -`kubeStateMetrics.serviceAccountName` | service account name for kube-state-metrics to use (ignored if rbac.create=true) | `default` -`kubeStateMetrics.service.annotations` | annotations for kube-state-metrics service | `{prometheus.io/scrape: "true"}` -`kubeStateMetrics.service.clusterIP` | internal kube-state-metrics cluster service IP | `None` -`kubeStateMetrics.service.externalIPs` | kube-state-metrics service external IP addresses | `[]` -`kubeStateMetrics.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` -`kubeStateMetrics.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` -`kubeStateMetrics.service.servicePort` | kube-state-metrics service port | `80` -`kubeStateMetrics.service.type` | type of kube-state-metrics service to create | `ClusterIP` -`nodeExporter.enabled` | If true, create node-exporter | `true` -`nodeExporter.name` | node-exporter container name | `node-exporter` -`nodeExporter.image.repository` | node-exporter container image repository| `prom/node-exporter` -`nodeExporter.image.tag` | node-exporter container image tag | `v0.13.0` -`nodeExporter.image.pullPolicy` | node-exporter container image pull policy | `IfNotPresent` -`nodeExporter.extraArgs` | Additional node-exporter container arguments | `{}` -`nodeExporter.extraHostPathMounts` | Additional node-exporter hostPath mounts | `[]` -`nodeExporter.nodeSelector` | node labels for node-exporter pod assignment | `{}` -`nodeExporter.podAnnotations` | annotations to be added to node-exporter pods | `{}` -`nodeExporter.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` -`nodeExporter.resources` | node-exporter resource requests and limits (YAML) | `{}` -`nodeExporter.serviceAccountName` | service account name for node-exporter to use (ignored if rbac.create=true) | `default` -`nodeExporter.service.annotations` | annotations for node-exporter service | `{prometheus.io/scrape: "true"}` -`nodeExporter.service.clusterIP` | internal node-exporter cluster service IP | `None` -`nodeExporter.service.externalIPs` | node-exporter service external IP addresses | `[]` -`nodeExporter.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` -`nodeExporter.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` -`nodeExporter.service.servicePort` | node-exporter service port | `9100` -`nodeExporter.service.type` | type of node-exporter service to create | `ClusterIP` -`pushgateway.enabled` | If true, create pushgateway | `true` -`pushgateway.name` | pushgateway container name | `pushgateway` -`pushgateway.image.repository` | pushgateway container image repository | `prom/pushgateway` -`pushgateway.image.tag` | pushgateway container image tag | `v0.4.0` -`pushgateway.image.pullPolicy` | pushgateway container image pull policy | `IfNotPresent` -`pushgateway.extraArgs` | Additional pushgateway container arguments | `{}` -`pushgateway.ingress.enabled` | If true, pushgateway Ingress will be created | `false` -`pushgateway.ingress.annotations` | pushgateway Ingress annotations | `{}` -`pushgateway.ingress.hosts` | pushgateway Ingress hostnames | `[]` -`pushgateway.ingress.tls` | pushgateway Ingress TLS configuration (YAML) | `[]` -`pushgateway.nodeSelector` | node labels for pushgateway pod assignment | `{}` -`pushgateway.podAnnotations` | annotations to be added to pushgateway pods | `{}` -`pushgateway.replicaCount` | desired number of pushgateway pods | `1` -`pushgateway.resources` | pushgateway pod resource requests & limits | `{}` -`pushgateway.service.annotations` | annotations for pushgateway service | `{}` -`pushgateway.service.clusterIP` | internal pushgateway cluster service IP | `""` -`pushgateway.service.externalIPs` | pushgateway service external IP addresses | `[]` -`pushgateway.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` -`pushgateway.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` -`pushgateway.service.servicePort` | pushgateway service port | `9091` -`pushgateway.service.type` | type of pushgateway service to create | `ClusterIP` -`rbac.create` | If true, create & use RBAC resources | `false` -`server.name` | Prometheus server container name | `server` -`server.image.repository` | Prometheus server container image repository | `prom/prometheus` -`server.image.tag` | Prometheus server container image tag | `v1.5.1` -`server.image.pullPolicy` | Prometheus server container image pull policy | `IfNotPresent` -`server.alertmanagerURL` | (optional) alertmanager URL; only used if alertmanager.enabled = false | `""` -`server.extraArgs` | Additional Prometheus server container arguments | `{}` -`server.baseURL` | The prefix slug at which the server can be accessed | `` -`server.extraHostPathMounts` | Additional Prometheus server hostPath mounts | `[]` -`server.configMapOverrideName` | Prometheus server ConfigMap override where full-name is `{{.Release.Name}}-{{.Values.server.configMapOverrideName}}` and setting this value will prevent the default server ConfigMap from being generated | `""` -`server.ingress.enabled` | If true, Prometheus server Ingress will be created | `false` -`server.ingress.annotations` | Prometheus server Ingress annotations | `[]` -`server.ingress.hosts` | Prometheus server Ingress hostnames | `[]` -`server.ingress.tls` | Prometheus server Ingress TLS configuration (YAML) | `[]` -`server.nodeSelector` | node labels for Prometheus server pod assignment | `{}` -`server.tolerations` | node taints to tolerate (requires Kubernetes >=1.6) | `[]` -`server.persistentVolume.enabled` | If true, Prometheus server will create a Persistent Volume Claim | `true` -`server.persistentVolume.accessModes` | Prometheus server data Persistent Volume access modes | `[ReadWriteOnce]` -`server.persistentVolume.annotations` | Prometheus server data Persistent Volume annotations | `{}` -`server.persistentVolume.existingClaim` | Prometheus server data Persistent Volume existing claim name | `""` -`server.persistentVolume.mountPath` | Prometheus server data Persistent Volume mount root path | `/data` -`server.persistentVolume.size` | Prometheus server data Persistent Volume size | `8Gi` -`server.persistentVolume.storageClass` | Prometheus server data Persistent Volume Storage Class | `unset` -`server.persistentVolume.subPath` | Subdirectory of Prometheus server data Persistent Volume to mount | `""` -`server.podAnnotations` | annotations to be added to Prometheus server pods | `{}` -`server.replicaCount` | desired number of Prometheus server pods | `1` -`server.resources` | Prometheus server resource requests and limits | `{}` -`server.serviceAccountName` | service account name for server to use (ignored if rbac.create=true) | `default` -`server.service.annotations` | annotations for Prometheus server service | `{}` -`server.service.clusterIP` | internal Prometheus server cluster service IP | `""` -`server.service.externalIPs` | Prometheus server service external IP addresses | `[]` -`server.service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `""` -`server.service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to load balancer (if supported) | `[]` -`server.service.nodePort` | Port to be used as the service NodePort (ignored if `server.service.type` is not `NodePort`) | `0` -`server.service.servicePort` | Prometheus server service port | `80` -`server.service.type` | type of Prometheus server service to create | `ClusterIP` -`server.terminationGracePeriodSeconds` | Prometheus server Pod termination grace period | `300` -`server.retention` | (optional) Prometheus data retention | `""` -`serverFiles.alerts` | Prometheus server alerts configuration | `""` -`serverFiles.rules` | Prometheus server rules configuration | `""` -`serverFiles.prometheus.yml` | Prometheus server scrape configuration | example configuration -`networkPolicy.enabled` | Enable NetworkPolicy | `false` | - -Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, - -```console -$ helm install stable/prometheus --name my-release \ - --set server.terminationGracePeriodSeconds=360 -``` - -Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example, - -```console -$ helm install stable/prometheus --name my-release -f values.yaml -``` - -> **Tip**: You can use the default [values.yaml](values.yaml) - -### ConfigMap Files -AlertManager is configured through [alertmanager.yml](https://prometheus.io/docs/alerting/configuration/). This file (and any others listed in `alertmanagerFiles`) will be mounted into the `alertmanager` pod. - -Prometheus is configured through [prometheus.yml](https://prometheus.io/docs/operating/configuration/). This file (and any others listed in `serverFiles`) will be mounted into the `server` pod. - -### Ingress TLS -If your cluster allows automatic creation/retrieval of TLS certificates (e.g. [kube-lego](https://github.com/jetstack/kube-lego)), please refer to the documentation for that mechanism. - -To manually configure TLS, first create/retrieve a key & certificate pair for the address(es) you wish to protect. Then create a TLS secret in the namespace: - -```console -kubectl create secret tls prometheus-server-tls --cert=path/to/tls.cert --key=path/to/tls.key -``` - -Include the secret's name, along with the desired hostnames, in the alertmanager/server Ingress TLS section of your custom `values.yaml` file: - -``` -server: - ingress: - ## If true, Prometheus server Ingress will be created - ## - enabled: true - - ## Prometheus server Ingress hostnames - ## Must be provided if Ingress is enabled - ## - hosts: - - prometheus.domain.com - - ## Prometheus server Ingress TLS configuration - ## Secrets must be manually created in the namespace - ## - tls: - - secretName: prometheus-server-tls - hosts: - - prometheus.domain.com -``` - -### NetworkPolicy - -Enabling Network Policy for Prometheus will secure connections to Alert Manager -and Kube State Metrics by only accepting connections from Prometheus Server. -All inbound connections to Prometheus Server are still allowed. - -To enable network policy for Prometheus, install a networking plugin that -implements the Kubernetes NetworkPolicy spec, and set `networkPolicy.enabled` to true. - -If NetworkPolicy is enabled for Prometheus' scrape targets, you may also need -to manually create a networkpolicy which allows it. diff --git a/charts/prometheus-dpc/templates/NOTES.txt b/charts/prometheus-dpc/templates/NOTES.txt deleted file mode 100755 index b4fcf54d5..000000000 --- a/charts/prometheus-dpc/templates/NOTES.txt +++ /dev/null @@ -1,100 +0,0 @@ -The Prometheus server can be accessed via port {{ .Values.server.service.servicePort }} on the following DNS name from within your cluster: -{{ template "prometheus.server.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - -{{ if .Values.server.ingress.enabled -}} -From outside the cluster, the server URL(s) are: -{{- range .Values.server.ingress.hosts }} -http://{{ . }} -{{- end }} -{{- else }} -Get the Prometheus server URL by running these commands in the same shell: -{{- if contains "NodePort" .Values.server.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.server.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.server.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.server.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.server.service.servicePort }} -{{- else if contains "ClusterIP" .Values.server.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.server.name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9090 -{{- end }} -{{- end }} - -{{- if .Values.server.persistentVolume.enabled }} -{{- else }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the Server pod is terminated. ##### -################################################################################# -{{- end }} - -{{ if .Values.alertmanager.enabled }} -The Prometheus alertmanager can be accessed via port {{ .Values.alertmanager.service.servicePort }} on the following DNS name from within your cluster: -{{ template "prometheus.alertmanager.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - -{{ if .Values.alertmanager.ingress.enabled -}} -From outside the cluster, the alertmanager URL(s) are: -{{- range .Values.alertmanager.ingress.hosts }} -http://{{ . }} -{{- end }} -{{- else }} -Get the Alertmanager URL by running these commands in the same shell: -{{- if contains "NodePort" .Values.alertmanager.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.alertmanager.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.alertmanager.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.alertmanager.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.alertmanager.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.alertmanager.service.servicePort }} -{{- else if contains "ClusterIP" .Values.alertmanager.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.alertmanager.name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9093 -{{- end }} -{{- end }} - -{{- if .Values.alertmanager.persistentVolume.enabled }} -{{- else }} -################################################################################# -###### WARNING: Persistence is disabled!!! You will lose your data when ##### -###### the AlertManager pod is terminated. ##### -################################################################################# -{{- end }} -{{- end }} - -{{ if .Values.pushgateway.enabled }} -The Prometheus PushGateway can be accessed via port {{ .Values.pushgateway.service.servicePort }} on the following DNS name from within your cluster: -{{ template "prometheus.pushgateway.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local - -{{ if .Values.pushgateway.ingress.enabled -}} -From outside the cluster, the pushgateway URL(s) are: -{{- range .Values.pushgateway.ingress.hosts }} -http://{{ . }} -{{- end }} -{{- else }} -Get the PushGateway URL by running these commands in the same shell: -{{- if contains "NodePort" .Values.pushgateway.service.type }} - export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "prometheus.pushgateway.fullname" . }}) - export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") - echo http://$NODE_IP:$NODE_PORT -{{- else if contains "LoadBalancer" .Values.pushgateway.service.type }} - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "prometheus.pushgateway.fullname" . }}' - - export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "prometheus.pushgateway.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - echo http://$SERVICE_IP:{{ .Values.pushgateway.service.servicePort }} -{{- else if contains "ClusterIP" .Values.pushgateway.service.type }} - export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "prometheus.name" . }},component={{ .Values.pushgateway.name }}" -o jsonpath="{.items[0].metadata.name}") - kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9093 -{{- end }} -{{- end }} -{{- end }} - -For more information on running Prometheus, visit: -https://prometheus.io/ diff --git a/charts/prometheus-dpc/templates/_helpers.tpl b/charts/prometheus-dpc/templates/_helpers.tpl deleted file mode 100755 index baa0a94a5..000000000 --- a/charts/prometheus-dpc/templates/_helpers.tpl +++ /dev/null @@ -1,72 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "prometheus.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified alertmanager name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.alertmanager.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.alertmanager.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified kube-state-metrics name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.kubeStateMetrics.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.kubeStateMetrics.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified node-exporter name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.nodeExporter.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.nodeExporter.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified Prometheus server name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.server.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.server.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a fully qualified pushgateway name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "prometheus.pushgateway.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s-%s" .Release.Name $name .Values.pushgateway.name | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for networkpolicy. -*/}} -{{- define "prometheus.networkPolicy.apiVersion" -}} -{{- if and (ge .Capabilities.KubeVersion.Minor "4") (le .Capabilities.KubeVersion.Minor "6") -}} -{{- print "extensions/v1beta1" -}} -{{- else if ge .Capabilities.KubeVersion.Minor "7" -}} -{{- print "networking.k8s.io/v1" -}} -{{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/alertmanager-clusterrolebinding.yaml b/charts/prometheus-dpc/templates/alertmanager-clusterrolebinding.yaml deleted file mode 100755 index e6d9b4c32..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "prometheus.alertmanager.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -{{- end }} diff --git a/charts/prometheus-dpc/templates/alertmanager-configmap.yaml b/charts/prometheus-dpc/templates/alertmanager-configmap.yaml deleted file mode 100755 index c529365df..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-configmap.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if and .Values.alertmanager.enabled (empty .Values.alertmanager.configMapOverrideName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -data: -{{ toYaml .Values.alertmanagerFiles | indent 2 }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/alertmanager-deployment.yaml b/charts/prometheus-dpc/templates/alertmanager-deployment.yaml deleted file mode 100755 index 269344b52..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-deployment.yaml +++ /dev/null @@ -1,93 +0,0 @@ -{{- if .Values.alertmanager.enabled -}} -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -spec: - replicas: {{ .Values.alertmanager.replicaCount }} - {{- if .Values.server.strategy }} - strategy: -{{ toYaml .Values.server.strategy | indent 4 }} - {{- end }} - template: - metadata: - {{- if .Values.alertmanager.podAnnotations }} - annotations: -{{ toYaml .Values.alertmanager.podAnnotations | indent 8 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.alertmanager.name }}" - release: {{ .Release.Name }} - spec: - serviceAccountName: {{ if .Values.rbac.create }}{{ template "prometheus.alertmanager.fullname" . }}{{ else }}"{{ .Values.alertmanager.serviceAccountName }}"{{ end }} - containers: - - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }} - image: "{{ .Values.alertmanager.image.repository }}:{{ .Values.alertmanager.image.tag }}" - imagePullPolicy: "{{ .Values.alertmanager.image.pullPolicy }}" - env: - {{- range $key, $value := .Values.alertmanager.extraEnv }} - - name: {{ $key }} - value: {{ $value }} - {{- end }} - args: - - --config.file=/etc/config/alertmanager.yml - - --storage.path={{ .Values.alertmanager.persistentVolume.mountPath }} - {{- range $key, $value := .Values.alertmanager.extraArgs }} - - --{{ $key }}={{ $value }} - {{- end }} - ports: - - containerPort: 9093 - readinessProbe: - httpGet: - path: {{ .Values.alertmanager.baseURL }}/#/status - port: 9093 - initialDelaySeconds: 30 - timeoutSeconds: 30 - resources: -{{ toYaml .Values.alertmanager.resources | indent 12 }} - volumeMounts: - - name: config-volume - mountPath: /etc/config - - name: storage-volume - mountPath: "{{ .Values.alertmanager.persistentVolume.mountPath }}" - subPath: "{{ .Values.alertmanager.persistentVolume.subPath }}" - - - name: {{ template "prometheus.name" . }}-{{ .Values.alertmanager.name }}-{{ .Values.configmapReload.name }} - image: "{{ .Values.configmapReload.image.repository }}:{{ .Values.configmapReload.image.tag }}" - imagePullPolicy: "{{ .Values.configmapReload.image.pullPolicy }}" - args: - - --volume-dir=/etc/config - - --webhook-url=http://localhost:9093{{ .Values.alertmanager.baseURL }}/-/reload - resources: -{{ toYaml .Values.configmapReload.resources | indent 12 }} - volumeMounts: - - name: config-volume - mountPath: /etc/config - readOnly: true - {{- if .Values.alertmanager.nodeSelector }} - nodeSelector: -{{ toYaml .Values.alertmanager.nodeSelector | indent 8 }} - {{- end }} - {{- if .Values.alertmanager.affinity }} - affinity: -{{ toYaml .Values.alertmanager.affinity | indent 8 }} - {{- end }} - volumes: - - name: config-volume - configMap: - name: {{ if .Values.alertmanager.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.alertmanager.configMapOverrideName }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} - - name: storage-volume - {{- if .Values.alertmanager.persistentVolume.enabled }} - persistentVolumeClaim: - claimName: {{ if .Values.alertmanager.persistentVolume.existingClaim }}{{ .Values.alertmanager.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.alertmanager.fullname" . }}{{- end }} - {{- else }} - emptyDir: {} - {{- end -}} -{{- end }} diff --git a/charts/prometheus-dpc/templates/alertmanager-ingress.yaml b/charts/prometheus-dpc/templates/alertmanager-ingress.yaml deleted file mode 100755 index 42e22165e..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-ingress.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.ingress.enabled -}} -{{- $releaseName := .Release.Name -}} -{{- $serviceName := include "prometheus.alertmanager.fullname" . }} -{{- $servicePort := .Values.alertmanager.service.servicePort -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: -{{- if .Values.alertmanager.ingress.annotations }} - annotations: -{{ toYaml .Values.alertmanager.ingress.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -spec: - rules: - {{- range .Values.alertmanager.ingress.hosts }} - - host: {{ . }} - http: - paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} -{{- if .Values.alertmanager.ingress.tls }} - tls: -{{ toYaml .Values.alertmanager.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/alertmanager-networkpolicy.yaml b/charts/prometheus-dpc/templates/alertmanager-networkpolicy.yaml deleted file mode 100755 index 9f5a7cae2..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-networkpolicy.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} -kind: NetworkPolicy -metadata: - name: {{ template "prometheus.alertmanager.fullname" . }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - podSelector: - matchLabels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.alertmanager.name }}" - release: {{ .Release.Name }} - ingress: - - from: - - podSelector: - matchLabels: - release: {{ .Release.Name }} - component: "{{ .Values.server.name }}" - - ports: - - port: 9093 -{{- end }} diff --git a/charts/prometheus-dpc/templates/alertmanager-pvc.yaml b/charts/prometheus-dpc/templates/alertmanager-pvc.yaml deleted file mode 100755 index c93db4ccd..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-pvc.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if and .Values.alertmanager.enabled .Values.alertmanager.persistentVolume.enabled -}} -{{- if not .Values.alertmanager.persistentVolume.existingClaim -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - {{- if .Values.alertmanager.persistentVolume.annotations }} - annotations: -{{ toYaml .Values.alertmanager.persistentVolume.annotations | indent 4 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -spec: - accessModes: -{{ toYaml .Values.alertmanager.persistentVolume.accessModes | indent 4 }} -{{- if .Values.alertmanager.persistentVolume.storageClass }} -{{- if (eq "-" .Values.alertmanager.persistentVolume.storageClass) }} - storageClassName: "" -{{- else }} - storageClassName: "{{ .Values.alertmanager.persistentVolume.storageClass }}" -{{- end }} -{{- end }} - resources: - requests: - storage: "{{ .Values.alertmanager.persistentVolume.size }}" -{{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/alertmanager-service.yaml b/charts/prometheus-dpc/templates/alertmanager-service.yaml deleted file mode 100755 index 2521e4502..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-service.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if .Values.alertmanager.enabled -}} -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.alertmanager.service.annotations }} - annotations: -{{ toYaml .Values.alertmanager.service.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -{{- if .Values.alertmanager.service.labels }} -{{ toYaml .Values.alertmanager.service.labels | indent 4 }} -{{- end }} - name: {{ template "prometheus.alertmanager.fullname" . }} -spec: -{{- if .Values.alertmanager.service.clusterIP }} - clusterIP: {{ .Values.alertmanager.service.clusterIP }} -{{- end }} -{{- if .Values.alertmanager.service.externalIPs }} - externalIPs: -{{ toYaml .Values.alertmanager.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.alertmanager.service.loadBalancerIP }} -{{- end }} -{{- if .Values.alertmanager.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.alertmanager.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: http - port: {{ .Values.alertmanager.service.servicePort }} - protocol: TCP - targetPort: 9093 - {{- if .Values.alertmanager.service.nodePort }} - nodePort: {{ .Values.alertmanager.service.nodePort }} - {{- end }} - selector: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.alertmanager.name }}" - release: {{ .Release.Name }} - type: "{{ .Values.alertmanager.service.type }}" -{{- end }} diff --git a/charts/prometheus-dpc/templates/alertmanager-serviceaccount.yaml b/charts/prometheus-dpc/templates/alertmanager-serviceaccount.yaml deleted file mode 100755 index e778983a6..000000000 --- a/charts/prometheus-dpc/templates/alertmanager-serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.alertmanager.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.alertmanager.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-clusterrole.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-clusterrole.yaml deleted file mode 100755 index 2b25cc2b7..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-clusterrole.yaml +++ /dev/null @@ -1,53 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -rules: - - apiGroups: - - "" - resources: - - namespaces - - nodes - - persistentvolumeclaims - - pods - - services - - resourcequotas - - replicationcontrollers - - limitranges - - persistentvolumeclaims - verbs: - - list - - watch - - apiGroups: - - extensions - resources: - - daemonsets - - deployments - - replicasets - verbs: - - list - - watch - - apiGroups: - - apps - resources: - - statefulsets - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - cronjobs - - jobs - verbs: - - list - - watch -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-clusterrolebinding.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-clusterrolebinding.yaml deleted file mode 100755 index cd3ad0251..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-deployment.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-deployment.yaml deleted file mode 100755 index 63fae7a56..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -{{- if .Values.kubeStateMetrics.enabled -}} -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -spec: - replicas: {{ .Values.kubeStateMetrics.replicaCount }} - template: - metadata: - {{- if .Values.kubeStateMetrics.podAnnotations }} - annotations: -{{ toYaml .Values.kubeStateMetrics.podAnnotations | indent 8 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.kubeStateMetrics.name }}" - release: {{ .Release.Name }} - spec: - serviceAccountName: {{ if .Values.rbac.create }}{{ template "prometheus.kubeStateMetrics.fullname" . }}{{ else }}"{{ .Values.kubeStateMetrics.serviceAccountName }}"{{ end }} - containers: - - name: {{ template "prometheus.name" . }}-{{ .Values.kubeStateMetrics.name }} - image: "{{ .Values.kubeStateMetrics.image.repository }}:{{ .Values.kubeStateMetrics.image.tag }}" - imagePullPolicy: "{{ .Values.kubeStateMetrics.image.pullPolicy }}" - ports: - - name: metrics - containerPort: 8080 - resources: -{{ toYaml .Values.kubeStateMetrics.resources | indent 12 }} - {{- if .Values.kubeStateMetrics.nodeSelector }} - nodeSelector: -{{ toYaml .Values.kubeStateMetrics.nodeSelector | indent 8 }} - {{- end }} - {{- if .Values.kubeStateMetrics.affinity }} - affinity: -{{ toYaml .Values.kubeStateMetrics.affinity | indent 8 }} - {{- end }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-networkpolicy.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-networkpolicy.yaml deleted file mode 100755 index 3fc62e200..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-networkpolicy.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} -kind: NetworkPolicy -metadata: - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - podSelector: - matchLabels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.kubeStateMetrics.name }}" - release: {{ .Release.Name }} - ingress: - - from: - - podSelector: - matchLabels: - release: {{ .Release.Name }} - component: "{{ .Values.server.name }}" - - ports: - - port: 8080 -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-serviceaccount.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-serviceaccount.yaml deleted file mode 100755 index 730668870..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/kube-state-metrics-svc.yaml b/charts/prometheus-dpc/templates/kube-state-metrics-svc.yaml deleted file mode 100755 index e11fa06a4..000000000 --- a/charts/prometheus-dpc/templates/kube-state-metrics-svc.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.kubeStateMetrics.enabled -}} -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.kubeStateMetrics.service.annotations }} - annotations: -{{ toYaml .Values.kubeStateMetrics.service.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.kubeStateMetrics.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -{{- if .Values.kubeStateMetrics.service.labels }} -{{ toYaml .Values.kubeStateMetrics.service.labels | indent 4 }} -{{- end }} - name: {{ template "prometheus.kubeStateMetrics.fullname" . }} -spec: -{{- if .Values.kubeStateMetrics.service.clusterIP }} - clusterIP: {{ .Values.kubeStateMetrics.service.clusterIP }} -{{- end }} -{{- if .Values.kubeStateMetrics.service.externalIPs }} - externalIPs: -{{ toYaml .Values.kubeStateMetrics.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.kubeStateMetrics.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.kubeStateMetrics.service.loadBalancerIP }} -{{- end }} -{{- if .Values.kubeStateMetrics.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.kubeStateMetrics.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: http - port: {{ .Values.kubeStateMetrics.service.servicePort }} - protocol: TCP - targetPort: 8080 - selector: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.kubeStateMetrics.name }}" - release: {{ .Release.Name }} - type: "{{ .Values.kubeStateMetrics.service.type }}" -{{- end }} diff --git a/charts/prometheus-dpc/templates/node-exporter-clusterrolebinding.yaml b/charts/prometheus-dpc/templates/node-exporter-clusterrolebinding.yaml deleted file mode 100755 index ed4710e28..000000000 --- a/charts/prometheus-dpc/templates/node-exporter-clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.nodeExporter.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.nodeExporter.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "prometheus.nodeExporter.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: cluster-admin -{{- end }} diff --git a/charts/prometheus-dpc/templates/node-exporter-daemonset.yaml b/charts/prometheus-dpc/templates/node-exporter-daemonset.yaml deleted file mode 100755 index db04c0749..000000000 --- a/charts/prometheus-dpc/templates/node-exporter-daemonset.yaml +++ /dev/null @@ -1,79 +0,0 @@ -{{- if .Values.nodeExporter.enabled -}} -apiVersion: extensions/v1beta1 -kind: DaemonSet -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.nodeExporter.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.nodeExporter.fullname" . }} -spec: - {{- if .Values.nodeExporter.updateStrategy }} - updateStrategy: -{{ toYaml .Values.nodeExporter.updateStrategy | indent 4 }} - {{- end }} - template: - metadata: - {{- if .Values.nodeExporter.podAnnotations }} - annotations: -{{ toYaml .Values.nodeExporter.podAnnotations | indent 8 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.nodeExporter.name }}" - release: {{ .Release.Name }} - spec: - serviceAccountName: {{ if .Values.rbac.create }}{{ template "prometheus.nodeExporter.fullname" . }}{{ else }}"{{ .Values.nodeExporter.serviceAccountName }}"{{ end }} - containers: - - name: {{ template "prometheus.name" . }}-{{ .Values.nodeExporter.name }} - image: "{{ .Values.nodeExporter.image.repository }}:{{ .Values.nodeExporter.image.tag }}" - imagePullPolicy: "{{ .Values.nodeExporter.image.pullPolicy }}" - args: - - --path.procfs=/host/proc - - --path.sysfs=/host/sys - {{- range $key, $value := .Values.nodeExporter.extraArgs }} - - --{{ $key }}={{ $value }} - {{- end }} - ports: - - name: metrics - containerPort: 9100 - hostPort: {{ .Values.nodeExporter.service.hostPort }} - resources: -{{ toYaml .Values.nodeExporter.resources | indent 12 }} - volumeMounts: - - name: proc - mountPath: /host/proc - readOnly: true - - name: sys - mountPath: /host/sys - readOnly: true - {{- range .Values.nodeExporter.extraHostPathMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - {{- end }} - hostNetwork: true - hostPID: true - {{- if .Values.nodeExporter.tolerations }} - tolerations: -{{ toYaml .Values.nodeExporter.tolerations | indent 8 }} - {{- end }} - {{- if .Values.nodeExporter.nodeSelector }} - nodeSelector: -{{ toYaml .Values.nodeExporter.nodeSelector | indent 8 }} - {{- end }} - volumes: - - name: proc - hostPath: - path: /proc - - name: sys - hostPath: - path: /sys - {{- range .Values.nodeExporter.extraHostPathMounts }} - - name: {{ .name }} - hostPath: - path: {{ .hostPath }} - {{- end }} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/node-exporter-service.yaml b/charts/prometheus-dpc/templates/node-exporter-service.yaml deleted file mode 100755 index 6af14c26c..000000000 --- a/charts/prometheus-dpc/templates/node-exporter-service.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.nodeExporter.enabled -}} -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.nodeExporter.service.annotations }} - annotations: -{{ toYaml .Values.nodeExporter.service.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.nodeExporter.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -{{- if .Values.nodeExporter.service.labels }} -{{ toYaml .Values.nodeExporter.service.labels | indent 4 }} -{{- end }} - name: {{ template "prometheus.nodeExporter.fullname" . }} -spec: -{{- if .Values.nodeExporter.service.clusterIP }} - clusterIP: {{ .Values.nodeExporter.service.clusterIP }} -{{- end }} -{{- if .Values.nodeExporter.service.externalIPs }} - externalIPs: -{{ toYaml .Values.nodeExporter.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.nodeExporter.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.nodeExporter.service.loadBalancerIP }} -{{- end }} -{{- if .Values.nodeExporter.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.nodeExporter.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: metrics - port: {{ .Values.nodeExporter.service.servicePort }} - protocol: TCP - targetPort: 9100 - selector: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.nodeExporter.name }}" - release: {{ .Release.Name }} - type: "{{ .Values.nodeExporter.service.type }}" -{{- end -}} diff --git a/charts/prometheus-dpc/templates/node-exporter-serviceaccount.yaml b/charts/prometheus-dpc/templates/node-exporter-serviceaccount.yaml deleted file mode 100755 index 1537984ab..000000000 --- a/charts/prometheus-dpc/templates/node-exporter-serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.nodeExporter.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.nodeExporter.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/openshift-scc.yaml b/charts/prometheus-dpc/templates/openshift-scc.yaml deleted file mode 100644 index 81eda4222..000000000 --- a/charts/prometheus-dpc/templates/openshift-scc.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# {{- if .Values.openshift -}} -# kind: SecurityContextConstraints -# apiVersion: v1 -# metadata: -# labels: -# app: {{ template "prometheus.name" . }} -# chart: {{ .Chart.Name }}-{{ .Chart.Version }} -# component: "{{ .Values.server.name }}" -# heritage: {{ .Release.Service }} -# release: {{ .Release.Name }} -# name: {{ template "prometheus.server.fullname" . }} -# runAsUser: -# type: RunAsAny -# seLinuxContext: -# type: MustRunAs -# fsGroup: -# type: RunAsAny -# supplementalGroups: -# type: RunAsAny -# allowHostDirVolumePlugin: false -# allowHostIPC: false -# allowHostNetwork: true -# allowHostPID: true -# allowHostPorts: false -# allowPrivilegedContainer: false -# readOnlyRootFilesystem: false -# priority: null -# allowedCapabilities: [] -# defaultAddCapabilities: [] -# requiredDropCapabilities: -# - KILL -# - MKNOD -# - SYS_CHROOT -# - SETUID -# - SETGID -# volumes: -# - configMap -# - downwardAPI -# - emptyDir -# - persistentVolumeClaim -# - projected -# - secret -# {{- end -}} diff --git a/charts/prometheus-dpc/templates/pushgateway-deployment.yaml b/charts/prometheus-dpc/templates/pushgateway-deployment.yaml deleted file mode 100755 index 645882757..000000000 --- a/charts/prometheus-dpc/templates/pushgateway-deployment.yaml +++ /dev/null @@ -1,51 +0,0 @@ -{{- if .Values.pushgateway.enabled -}} -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.pushgateway.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.pushgateway.fullname" . }} -spec: - replicas: {{ .Values.pushgateway.replicaCount }} - template: - metadata: - {{- if .Values.pushgateway.podAnnotations }} - annotations: -{{ toYaml .Values.pushgateway.podAnnotations | indent 8 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.pushgateway.name }}" - release: {{ .Release.Name }} - spec: - containers: - - name: {{ template "prometheus.name" . }}-{{ .Values.pushgateway.name }} - image: "{{ .Values.pushgateway.image.repository }}:{{ .Values.pushgateway.image.tag }}" - imagePullPolicy: "{{ .Values.pushgateway.image.pullPolicy }}" - args: - {{- range $key, $value := .Values.pushgateway.extraArgs }} - - --{{ $key }}={{ $value }} - {{- end }} - ports: - - containerPort: 9091 - readinessProbe: - httpGet: - path: /#/status - port: 9091 - initialDelaySeconds: 10 - timeoutSeconds: 10 - resources: -{{ toYaml .Values.pushgateway.resources | indent 12 }} - {{- if .Values.pushgateway.nodeSelector }} - nodeSelector: -{{ toYaml .Values.pushgateway.nodeSelector | indent 8 }} - {{- end }} - {{- if .Values.pushgateway.affinity }} - affinity: -{{ toYaml .Values.pushgateway.affinity | indent 8 }} - {{- end }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/pushgateway-ingress.yaml b/charts/prometheus-dpc/templates/pushgateway-ingress.yaml deleted file mode 100755 index 158178924..000000000 --- a/charts/prometheus-dpc/templates/pushgateway-ingress.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if and .Values.pushgateway.enabled .Values.pushgateway.ingress.enabled -}} -{{- $releaseName := .Release.Name -}} -{{- $serviceName := include "prometheus.pushgateway.fullname" . }} -{{- $servicePort := .Values.pushgateway.service.servicePort -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: -{{- if .Values.pushgateway.ingress.annotations }} - annotations: -{{ toYaml .Values.pushgateway.ingress.annotations | indent 4}} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.pushgateway.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.pushgateway.fullname" . }} -spec: - rules: - {{- range .Values.pushgateway.ingress.hosts }} - - host: {{ . }} - http: - paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} -{{- if .Values.pushgateway.ingress.tls }} - tls: -{{ toYaml .Values.pushgateway.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/pushgateway-service.yaml b/charts/prometheus-dpc/templates/pushgateway-service.yaml deleted file mode 100755 index 968631910..000000000 --- a/charts/prometheus-dpc/templates/pushgateway-service.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{- if .Values.pushgateway.enabled -}} -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.pushgateway.service.annotations }} - annotations: -{{ toYaml .Values.pushgateway.service.annotations | indent 4}} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.pushgateway.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -{{- if .Values.pushgateway.service.labels }} -{{ toYaml .Values.pushgateway.service.labels | indent 4}} -{{- end }} - name: {{ template "prometheus.pushgateway.fullname" . }} -spec: -{{- if .Values.pushgateway.service.clusterIP }} - clusterIP: {{ .Values.pushgateway.service.clusterIP }} -{{- end }} -{{- if .Values.pushgateway.service.externalIPs }} - externalIPs: -{{ toYaml .Values.pushgateway.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.pushgateway.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.pushgateway.service.loadBalancerIP }} -{{- end }} -{{- if .Values.pushgateway.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.pushgateway.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: http - port: {{ .Values.pushgateway.service.servicePort }} - protocol: TCP - targetPort: 9091 - selector: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.pushgateway.name }}" - release: {{ .Release.Name }} - type: "{{ .Values.pushgateway.service.type }}" -{{- end }} diff --git a/charts/prometheus-dpc/templates/server-clusterrole.yaml b/charts/prometheus-dpc/templates/server-clusterrole.yaml deleted file mode 100755 index d9c6e4dae..000000000 --- a/charts/prometheus-dpc/templates/server-clusterrole.yaml +++ /dev/null @@ -1,35 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRole -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -rules: - - apiGroups: - - "" - resources: - - nodes - - nodes/proxy - - services - - endpoints - - pods - verbs: - - get - - list - - watch - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - nonResourceURLs: - - "/metrics" - verbs: - - get -{{- end }} diff --git a/charts/prometheus-dpc/templates/server-clusterrolebinding.yaml b/charts/prometheus-dpc/templates/server-clusterrolebinding.yaml deleted file mode 100755 index 31964910e..000000000 --- a/charts/prometheus-dpc/templates/server-clusterrolebinding.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: rbac.authorization.k8s.io/v1beta1 -kind: ClusterRoleBinding -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -subjects: - - kind: ServiceAccount - name: {{ template "prometheus.server.fullname" . }} - namespace: {{ .Release.Namespace }} -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ template "prometheus.server.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/server-configmap.yaml b/charts/prometheus-dpc/templates/server-configmap.yaml deleted file mode 100755 index f4d47cddc..000000000 --- a/charts/prometheus-dpc/templates/server-configmap.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if (empty .Values.server.configMapOverrideName) -}} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -data: -{{ toYaml .Values.serverFiles | indent 2 }} -{{- end }} diff --git a/charts/prometheus-dpc/templates/server-deployment.yaml b/charts/prometheus-dpc/templates/server-deployment.yaml deleted file mode 100755 index c744313c2..000000000 --- a/charts/prometheus-dpc/templates/server-deployment.yaml +++ /dev/null @@ -1,109 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -spec: - replicas: {{ .Values.server.replicaCount }} - {{- if .Values.server.strategy }} - strategy: -{{ toYaml .Values.server.strategy | indent 4 }} - {{- end }} - template: - metadata: - {{- if .Values.server.podAnnotations }} - annotations: -{{ toYaml .Values.server.podAnnotations | indent 8 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.server.name }}" - release: {{ .Release.Name }} - spec: - serviceAccountName: {{ if .Values.rbac.create }}{{ template "prometheus.server.fullname" . }}{{ else }}"{{ .Values.server.serviceAccountName }}"{{ end }} - containers: - - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }}-{{ .Values.configmapReload.name }} - image: "{{ .Values.configmapReload.image.repository }}:{{ .Values.configmapReload.image.tag }}" - imagePullPolicy: "{{ .Values.configmapReload.image.pullPolicy }}" - args: - - --volume-dir=/etc/config - - --webhook-url=http://localhost:9090{{ .Values.server.baseURL }}/-/reload - resources: -{{ toYaml .Values.configmapReload.resources | indent 12 }} - volumeMounts: - - name: config-volume - mountPath: /etc/config - readOnly: true - - - name: {{ template "prometheus.name" . }}-{{ .Values.server.name }} - image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag }}" - imagePullPolicy: "{{ .Values.server.image.pullPolicy }}" - args: - {{- if or .Values.alertmanager.enabled .Values.server.alertmanagerURL }} - - --alertmanager.url={{- if .Values.alertmanager.enabled }}http://{{ template "prometheus.alertmanager.fullname" . }}:{{ .Values.alertmanager.service.servicePort }}{{ .Values.alertmanager.baseURL }}{{- else }}{{ .Values.server.alertmanagerURL }}{{- end }} - {{- end }} - {{- if .Values.server.retention }} - - --storage.local.retention={{ .Values.server.retention }} - {{- end }} - - --config.file=/etc/config/prometheus.yml - - --storage.local.path={{ .Values.server.persistentVolume.mountPath }} - - --web.console.libraries=/etc/prometheus/console_libraries - - --web.console.templates=/etc/prometheus/consoles - {{- range $key, $value := .Values.server.extraArgs }} - - --{{ $key }}={{ $value }} - {{- end }} - ports: - - containerPort: 9090 - readinessProbe: - httpGet: - path: {{ .Values.server.baseURL }}/status - port: 9090 - initialDelaySeconds: 30 - timeoutSeconds: 30 - resources: -{{ toYaml .Values.server.resources | indent 12 }} - volumeMounts: - - name: config-volume - mountPath: /etc/config - - name: storage-volume - mountPath: {{ .Values.alertmanager.persistentVolume.mountPath }} - subPath: "{{ .Values.server.persistentVolume.subPath }}" - {{- range .Values.server.extraHostPathMounts }} - - name: {{ .name }} - mountPath: {{ .mountPath }} - readOnly: {{ .readOnly }} - {{- end }} - {{- if .Values.server.nodeSelector }} - nodeSelector: -{{ toYaml .Values.server.nodeSelector | indent 8 }} - {{- end }} - {{- if .Values.server.tolerations }} - tolerations: -{{ toYaml .Values.server.tolerations | indent 8 }} - {{- end }} - {{- if .Values.server.affinity }} - affinity: -{{ toYaml .Values.server.affinity | indent 8 }} - {{- end }} - terminationGracePeriodSeconds: {{ .Values.server.terminationGracePeriodSeconds }} - volumes: - - name: config-volume - configMap: - name: {{ if .Values.server.configMapOverrideName }}{{ .Release.Name }}-{{ .Values.server.configMapOverrideName }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} - - name: storage-volume - {{- if .Values.server.persistentVolume.enabled }} - persistentVolumeClaim: - claimName: {{ if .Values.server.persistentVolume.existingClaim }}{{ .Values.server.persistentVolume.existingClaim }}{{- else }}{{ template "prometheus.server.fullname" . }}{{- end }} - {{- else }} - emptyDir: {} - {{- end -}} - {{- range .Values.server.extraHostPathMounts }} - - name: {{ .name }} - hostPath: - path: {{ .hostPath }} - {{- end }} diff --git a/charts/prometheus-dpc/templates/server-gluster-pvc.yaml b/charts/prometheus-dpc/templates/server-gluster-pvc.yaml deleted file mode 100644 index 3a78a7d8b..000000000 --- a/charts/prometheus-dpc/templates/server-gluster-pvc.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: prometheus-dpc-server - namespace: metrics -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 50Gi - storageClassName: gluster - volumeName: gluster-pv80 diff --git a/charts/prometheus-dpc/templates/server-ingress.yaml b/charts/prometheus-dpc/templates/server-ingress.yaml deleted file mode 100755 index e6009d501..000000000 --- a/charts/prometheus-dpc/templates/server-ingress.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.server.ingress.enabled -}} -{{- $releaseName := .Release.Name -}} -{{- $serviceName := include "prometheus.server.fullname" . }} -{{- $servicePort := .Values.server.service.servicePort -}} -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: -{{- if .Values.server.ingress.annotations }} - annotations: -{{ toYaml .Values.server.ingress.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -spec: - rules: - {{- range .Values.server.ingress.hosts }} - - host: {{ . }} - http: - paths: - - backend: - serviceName: {{ $serviceName }} - servicePort: {{ $servicePort }} - {{- end -}} -{{- if .Values.server.ingress.tls }} - tls: -{{ toYaml .Values.server.ingress.tls | indent 4 }} - {{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/server-networkpolicy.yaml b/charts/prometheus-dpc/templates/server-networkpolicy.yaml deleted file mode 100755 index 3f1cdcc66..000000000 --- a/charts/prometheus-dpc/templates/server-networkpolicy.yaml +++ /dev/null @@ -1,21 +0,0 @@ -{{- if .Values.networkPolicy.enabled }} -apiVersion: {{ template "prometheus.networkPolicy.apiVersion" . }} -kind: NetworkPolicy -metadata: - name: {{ template "prometheus.server.fullname" . }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -spec: - podSelector: - matchLabels: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.server.name }}" - release: {{ .Release.Name }} - ingress: - - ports: - - port: 9090 -{{- end }} diff --git a/charts/prometheus-dpc/templates/server-pvc.yaml b/charts/prometheus-dpc/templates/server-pvc.yaml deleted file mode 100755 index c4711e905..000000000 --- a/charts/prometheus-dpc/templates/server-pvc.yaml +++ /dev/null @@ -1,31 +0,0 @@ -{{- if .Values.server.persistentVolume.enabled -}} -{{- if not .Values.server.persistentVolume.existingClaim -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - {{- if .Values.server.persistentVolume.annotations }} - annotations: -{{ toYaml .Values.server.persistentVolume.annotations | indent 4 }} - {{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -spec: - accessModes: -{{ toYaml .Values.server.persistentVolume.accessModes | indent 4 }} -{{- if .Values.server.persistentVolume.storageClass }} -{{- if (eq "-" .Values.server.persistentVolume.storageClass) }} - storageClassName: "" -{{- else }} - storageClassName: "{{ .Values.server.persistentVolume.storageClass }}" -{{- end }} -{{- end }} - resources: - requests: - storage: "{{ .Values.server.persistentVolume.size }}" -{{- end -}} -{{- end -}} diff --git a/charts/prometheus-dpc/templates/server-route.yaml b/charts/prometheus-dpc/templates/server-route.yaml deleted file mode 100644 index f6152971c..000000000 --- a/charts/prometheus-dpc/templates/server-route.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- if .Values.openshift -}} -{{- $serviceName := include "prometheus.server.fullname" . }} -{{- $servicePort := .Values.server.service.servicePort -}} -apiVersion: route.openshift.io/v1 -kind: Route -metadata: -{{- if .Values.server.ingress.annotations }} - annotations: -{{ toYaml .Values.server.ingress.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -spec: - host: {{ .Values.server.ingress.hosts | first }} - to: - kind: Service - name: {{ $serviceName }} - weight: 100 - wildcardPolicy: None -{{- end -}} diff --git a/charts/prometheus-dpc/templates/server-service.yaml b/charts/prometheus-dpc/templates/server-service.yaml deleted file mode 100755 index be81694e2..000000000 --- a/charts/prometheus-dpc/templates/server-service.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: -{{- if .Values.server.service.annotations }} - annotations: -{{ toYaml .Values.server.service.annotations | indent 4 }} -{{- end }} - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} -{{- if .Values.server.service.labels }} -{{ toYaml .Values.server.service.labels | indent 4 }} -{{- end }} - name: {{ template "prometheus.server.fullname" . }} -spec: -{{- if .Values.server.service.clusterIP }} - clusterIP: {{ .Values.server.service.clusterIP }} -{{- end }} -{{- if .Values.server.service.externalIPs }} - externalIPs: -{{ toYaml .Values.server.service.externalIPs | indent 4 }} -{{- end }} -{{- if .Values.server.service.loadBalancerIP }} - loadBalancerIP: {{ .Values.server.service.loadBalancerIP }} -{{- end }} -{{- if .Values.server.service.loadBalancerSourceRanges }} - loadBalancerSourceRanges: - {{- range $cidr := .Values.server.service.loadBalancerSourceRanges }} - - {{ $cidr }} - {{- end }} -{{- end }} - ports: - - name: http - port: {{ .Values.server.service.servicePort }} - protocol: TCP - targetPort: 9090 - {{- if .Values.server.service.nodePort }} - nodePort: {{ .Values.server.service.nodePort }} - {{- end }} - selector: - app: {{ template "prometheus.name" . }} - component: "{{ .Values.server.name }}" - release: {{ .Release.Name }} - type: "{{ .Values.server.service.type }}" diff --git a/charts/prometheus-dpc/templates/server-serviceaccount.yaml b/charts/prometheus-dpc/templates/server-serviceaccount.yaml deleted file mode 100755 index a539b382f..000000000 --- a/charts/prometheus-dpc/templates/server-serviceaccount.yaml +++ /dev/null @@ -1,12 +0,0 @@ -{{- if .Values.rbac.create }} -apiVersion: v1 -kind: ServiceAccount -metadata: - labels: - app: {{ template "prometheus.name" . }} - chart: {{ .Chart.Name }}-{{ .Chart.Version }} - component: "{{ .Values.server.name }}" - heritage: {{ .Release.Service }} - release: {{ .Release.Name }} - name: {{ template "prometheus.server.fullname" . }} -{{- end }} diff --git a/charts/prometheus-dpc/values.yaml b/charts/prometheus-dpc/values.yaml deleted file mode 100755 index 05d66b675..000000000 --- a/charts/prometheus-dpc/values.yaml +++ /dev/null @@ -1,813 +0,0 @@ -rbac: - create: false - -openshift: false - -alertmanager: - ## If false, alertmanager will not be installed - ## - enabled: true - - # Defines the serviceAccountName to use when `rbac.create=false` - serviceAccountName: default - - ## alertmanager container name - ## - name: alertmanager - - ## alertmanager container image - ## - image: - repository: prom/alertmanager - tag: v0.9.1 - pullPolicy: IfNotPresent - - ## Additional alertmanager container arguments - ## - extraArgs: {} - - ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug - ## so that the various internal URLs are still able to access as they are in the default case. - ## (Optional) - baseURL: "" - - ## Additional alertmanager container environment variable - ## For instance to add a http_proxy - ## - extraEnv: {} - - ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.alertmanager.configMapOverrideName}} - ## Defining configMapOverrideName will cause templates/alertmanager-configmap.yaml - ## to NOT generate a ConfigMap resource - ## - configMapOverrideName: "" - - ingress: - ## If true, alertmanager Ingress will be created - ## - enabled: false - - ## alertmanager Ingress annotations - ## - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: 'true' - - ## alertmanager Ingress hostnames - ## Must be provided if Ingress is enabled - ## - hosts: [] - # - alertmanager.domain.com - - ## alertmanager Ingress TLS configuration - ## Secrets must be manually created in the namespace - ## - tls: [] - # - secretName: prometheus-alerts-tls - # hosts: - # - alertmanager.domain.com - - ## Alertmanager Deployment Strategy type - # strategy: - # type: Recreate - - ## Node labels for alertmanager pod assignment - ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - persistentVolume: - ## If true, alertmanager will create/use a Persistent Volume Claim - ## If false, use emptyDir - ## - enabled: true - - ## alertmanager data Persistent Volume access modes - ## Must match those of existing PV or dynamic provisioner - ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - accessModes: - - ReadWriteOnce - - ## alertmanager data Persistent Volume Claim annotations - ## - annotations: {} - - ## alertmanager data Persistent Volume existing claim name - ## Requires alertmanager.persistentVolume.enabled: true - ## If defined, PVC must be created manually before volume will be bound - existingClaim: "" - - ## alertmanager data Persistent Volume mount root path - ## - mountPath: /data - - ## alertmanager data Persistent Volume size - ## - size: 2Gi - - ## alertmanager data Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - ## Subdirectory of alertmanager data Persistent Volume to mount - ## Useful if the volume's root directory is not empty - ## - subPath: "" - - ## Annotations to be added to alertmanager pods - ## - podAnnotations: {} - - replicaCount: 1 - - ## alertmanager resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 10m - # memory: 32Mi - # requests: - # cpu: 10m - # memory: 32Mi - - service: - annotations: {} - labels: {} - clusterIP: "" - - ## List of IP addresses at which the alertmanager service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - loadBalancerIP: "" - loadBalancerSourceRanges: [] - servicePort: 80 - # nodePort: 30000 - type: ClusterIP - -## Monitors ConfigMap changes and POSTs to a URL -## Ref: https://github.com/jimmidyson/configmap-reload -## -configmapReload: - ## configmap-reload container name - ## - name: configmap-reload - - ## configmap-reload container image - ## - image: - repository: jimmidyson/configmap-reload - tag: v0.1 - pullPolicy: IfNotPresent - - ## configmap-reload resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - -kubeStateMetrics: - ## If false, kube-state-metrics will not be installed - ## - enabled: true - - # Defines the serviceAccountName to use when `rbac.create=false` - serviceAccountName: default - - ## kube-state-metrics container name - ## - name: kube-state-metrics - - ## kube-state-metrics container image - ## - image: - repository: gcr.io/google_containers/kube-state-metrics - tag: v1.1.0-rc.0 - pullPolicy: IfNotPresent - - ## Node labels for kube-state-metrics pod assignment - ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Annotations to be added to kube-state-metrics pods - ## - podAnnotations: {} - - replicaCount: 1 - - ## kube-state-metrics resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 10m - # memory: 16Mi - # requests: - # cpu: 10m - # memory: 16Mi - - service: - annotations: - prometheus.io/scrape: "true" - labels: {} - - clusterIP: None - - ## List of IP addresses at which the kube-state-metrics service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - loadBalancerIP: "" - loadBalancerSourceRanges: [] - servicePort: 80 - type: ClusterIP - -nodeExporter: - ## If false, node-exporter will not be installed - ## - enabled: true - - # Defines the serviceAccountName to use when `rbac.create=false` - serviceAccountName: default - - ## node-exporter container name - ## - name: node-exporter - - ## node-exporter container image - ## - image: - repository: prom/node-exporter - tag: v0.15.0 - pullPolicy: IfNotPresent - - ## Custom Update Strategy - ## - updateStrategy: - type: OnDelete - - ## Additional node-exporter container arguments - ## - extraArgs: {} - - ## Additional node-exporter hostPath mounts - ## - extraHostPathMounts: [] - # - name: textfile-dir - # mountPath: /srv/txt_collector - # hostPath: /var/lib/node-exporter - # readOnly: true - - ## Node tolerations for node-exporter scheduling to nodes with taints - ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal|Exists" - # value: "value" - # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" - - ## Node labels for node-exporter pod assignment - ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: - region: node - - ## Annotations to be added to node-exporter pods - ## - podAnnotations: {} - - ## node-exporter resource limits & requests - ## Ref: https://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 200m - # memory: 50Mi - # requests: - # cpu: 100m - # memory: 30Mi - - service: - annotations: - prometheus.io/scrape: "true" - labels: {} - - clusterIP: None - - ## List of IP addresses at which the node-exporter service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - hostPort: 9100 - loadBalancerIP: "" - loadBalancerSourceRanges: [] - servicePort: 9100 - type: ClusterIP - -server: - ## Prometheus server container name - ## - name: server - - # Defines the serviceAccountName to use when `rbac.create=false` - serviceAccountName: default - - ## Prometheus server container image - ## - image: - repository: prom/prometheus - tag: v1.8.1 - pullPolicy: IfNotPresent - - ## (optional) alertmanager URL - ## only used if alertmanager.enabled = false - alertmanagerURL: "" - - ## The URL prefix at which the container can be accessed. Useful in the case the '-web.external-url' includes a slug - ## so that the various internal URLs are still able to access as they are in the default case. - ## (Optional) - baseURL: "" - - ## Additional Prometheus server container arguments - ## - extraArgs: {} - - ## Additional Prometheus server hostPath mounts - ## - extraHostPathMounts: [] - # - name: certs-dir - # mountPath: /etc/kubernetes/certs - # hostPath: /etc/kubernetes/certs - # readOnly: true - - ## ConfigMap override where fullname is {{.Release.Name}}-{{.Values.server.configMapOverrideName}} - ## Defining configMapOverrideName will cause templates/server-configmap.yaml - ## to NOT generate a ConfigMap resource - ## - configMapOverrideName: "" - - ingress: - ## If true, Prometheus server Ingress will be created - ## - enabled: false - - ## Prometheus server Ingress annotations - ## - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: 'true' - - ## Prometheus server Ingress hostnames - ## Must be provided if Ingress is enabled - ## - hosts: [] - # - prometheus.domain.com - - ## Prometheus server Ingress TLS configuration - ## Secrets must be manually created in the namespace - ## - tls: [] - # - secretName: prometheus-server-tls - # hosts: - # - prometheus.domain.com - - ## Server Deployment Strategy type - # strategy: - # type: Recreate - - ## Node tolerations for server scheduling to nodes with taints - ## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ - ## - tolerations: [] - # - key: "key" - # operator: "Equal|Exists" - # value: "value" - # effect: "NoSchedule|PreferNoSchedule|NoExecute(1.6 only)" - - ## Node labels for Prometheus server pod assignment - ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ - nodeSelector: {} - - persistentVolume: - ## If true, Prometheus server will create/use a Persistent Volume Claim - ## If false, use emptyDir - ## - enabled: true - - ## Prometheus server data Persistent Volume access modes - ## Must match those of existing PV or dynamic provisioner - ## Ref: http://kubernetes.io/docs/user-guide/persistent-volumes/ - ## - accessModes: - - ReadWriteOnce - - ## Prometheus server data Persistent Volume annotations - ## - annotations: {} - - ## Prometheus server data Persistent Volume existing claim name - ## Requires server.persistentVolume.enabled: true - ## If defined, PVC must be created manually before volume will be bound - existingClaim: "" - - ## Prometheus server data Persistent Volume mount root path - ## - mountPath: /data - - ## Prometheus server data Persistent Volume size - ## - size: 8Gi - - ## Prometheus server data Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - - ## Subdirectory of Prometheus server data Persistent Volume to mount - ## Useful if the volume's root directory is not empty - ## - subPath: "" - - ## Annotations to be added to Prometheus server pods - ## - podAnnotations: {} - # iam.amazonaws.com/role: prometheus - - replicaCount: 1 - - ## Prometheus server resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 500m - # memory: 512Mi - # requests: - # cpu: 500m - # memory: 512Mi - - service: - annotations: {} - labels: {} - clusterIP: "" - - ## List of IP addresses at which the Prometheus server service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - loadBalancerIP: "" - loadBalancerSourceRanges: [] - servicePort: 80 - type: ClusterIP - - ## Prometheus server pod termination grace period - ## - terminationGracePeriodSeconds: 300 - - ## Prometheus data retention period (i.e 360h) - ## - retention: "" - -pushgateway: - ## If false, pushgateway will not be installed - ## - enabled: true - - ## pushgateway container name - ## - name: pushgateway - - ## pushgateway container image - ## - image: - repository: prom/pushgateway - tag: v0.4.0 - pullPolicy: IfNotPresent - - ## Additional pushgateway container arguments - ## - extraArgs: {} - - ingress: - ## If true, pushgateway Ingress will be created - ## - enabled: false - - ## pushgateway Ingress annotations - ## - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: 'true' - - ## pushgateway Ingress hostnames - ## Must be provided if Ingress is enabled - ## - hosts: [] - # - pushgateway.domain.com - - ## pushgateway Ingress TLS configuration - ## Secrets must be manually created in the namespace - ## - tls: [] - # - secretName: prometheus-alerts-tls - # hosts: - # - pushgateway.domain.com - - ## Node labels for pushgateway pod assignment - ## Ref: https://kubernetes.io/docs/user-guide/node-selection/ - ## - nodeSelector: {} - - ## Annotations to be added to pushgateway pods - ## - podAnnotations: {} - - replicaCount: 1 - - ## pushgateway resource requests and limits - ## Ref: http://kubernetes.io/docs/user-guide/compute-resources/ - ## - resources: {} - # limits: - # cpu: 10m - # memory: 32Mi - # requests: - # cpu: 10m - # memory: 32Mi - - service: - annotations: - prometheus.io/probe: pushgateway - labels: {} - clusterIP: "" - - ## List of IP addresses at which the pushgateway service is available - ## Ref: https://kubernetes.io/docs/user-guide/services/#external-ips - ## - externalIPs: [] - - loadBalancerIP: "" - loadBalancerSourceRanges: [] - servicePort: 9091 - type: ClusterIP - -## alertmanager ConfigMap entries -## -alertmanagerFiles: - alertmanager.yml: |- - global: - # slack_api_url: '' - - receivers: - - name: default-receiver - # slack_configs: - # - channel: '@you' - # send_resolved: true - - route: - group_wait: 10s - group_interval: 5m - receiver: default-receiver - repeat_interval: 3h - -## Prometheus server ConfigMap entries -## -serverFiles: - alerts: "" - rules: "" - - prometheus.yml: |- - rule_files: - - /etc/config/rules - - /etc/config/alerts - - scrape_configs: - - job_name: prometheus - static_configs: - - targets: - - localhost:9090 - - # A scrape configuration for running Prometheus on a Kubernetes cluster. - # This uses separate scrape configs for cluster components (i.e. API server, node) - # and services to allow each to use different authentication configs. - # - # Kubernetes labels will be added as Prometheus labels on metrics via the - # `labelmap` relabeling action. - - # Scrape config for API servers. - # - # Kubernetes exposes API servers as endpoints to the default/kubernetes - # service so this uses `endpoints` role and uses relabelling to only keep - # the endpoints associated with the default/kubernetes service using the - # default named port `https`. This works for single API server deployments as - # well as HA API server deployments. - - job_name: 'kubernetes-apiservers' - - kubernetes_sd_configs: - - role: endpoints - - # Default to scraping over https. If required, just disable this or change to - # `http`. - scheme: https - - # This TLS & bearer token file config is used to connect to the actual scrape - # endpoints for cluster components. This is separate to discovery auth - # configuration because discovery & scraping are two separate concerns in - # Prometheus. The discovery auth config is automatic if Prometheus runs inside - # the cluster. Otherwise, more config options have to be provided within the - # . - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - # If your node certificates are self-signed or use a different CA to the - # master CA, then disable certificate verification below. Note that - # certificate verification is an integral part of a secure infrastructure - # so this should only be disabled in a controlled environment. You can - # disable certificate verification by uncommenting the line below. - # - insecure_skip_verify: true - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - - # Keep only the default/kubernetes service endpoints for the https port. This - # will add targets for each API server which Kubernetes adds an endpoint to - # the default/kubernetes service. - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: default;kubernetes;https - - - job_name: 'kubernetes-nodes' - - # Default to scraping over https. If required, just disable this or change to - # `http`. - scheme: https - - # This TLS & bearer token file config is used to connect to the actual scrape - # endpoints for cluster components. This is separate to discovery auth - # configuration because discovery & scraping are two separate concerns in - # Prometheus. The discovery auth config is automatic if Prometheus runs inside - # the cluster. Otherwise, more config options have to be provided within the - # . - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - # If your node certificates are self-signed or use a different CA to the - # master CA, then disable certificate verification below. Note that - # certificate verification is an integral part of a secure infrastructure - # so this should only be disabled in a controlled environment. You can - # disable certificate verification by uncommenting the line below. - # - insecure_skip_verify: true - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - - kubernetes_sd_configs: - - role: node - - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics - - # Scrape config for service endpoints. - # - # The relabeling allows the actual service scrape endpoint to be configured - # via the following annotations: - # - # * `prometheus.io/scrape`: Only scrape services that have a value of `true` - # * `prometheus.io/scheme`: If the metrics endpoint is secured then you will need - # to set this to `https` & most likely set the `tls_config` of the scrape config. - # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. - # * `prometheus.io/port`: If the metrics are exposed on a different port to the - # service then set this appropriately. - - job_name: 'kubernetes-service-endpoints' - - kubernetes_sd_configs: - - role: endpoints - - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] - action: replace - target_label: __scheme__ - regex: (https?) - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] - action: replace - target_label: __address__ - regex: (.+)(?::\d+);(\d+) - replacement: $1:$2 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_name - - - job_name: 'prometheus-pushgateway' - honor_labels: true - - kubernetes_sd_configs: - - role: service - - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] - action: keep - regex: pushgateway - - # Example scrape config for probing services via the Blackbox Exporter. - # - # The relabeling allows the actual service scrape endpoint to be configured - # via the following annotations: - # - # * `prometheus.io/probe`: Only probe services that have a value of `true` - - job_name: 'kubernetes-services' - - metrics_path: /probe - params: - module: [http_2xx] - - kubernetes_sd_configs: - - role: service - - relabel_configs: - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] - action: keep - regex: true - - source_labels: [__address__] - target_label: __param_target - - target_label: __address__ - replacement: blackbox - - source_labels: [__param_target] - target_label: instance - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - target_label: kubernetes_name - - # Example scrape config for pods - # - # The relabeling allows the actual pod scrape endpoint to be configured via the - # following annotations: - # - # * `prometheus.io/scrape`: Only scrape pods that have a value of `true` - # * `prometheus.io/path`: If the metrics path is not `/metrics` override this. - # * `prometheus.io/port`: Scrape the pod on the indicated port instead of the default of `9102`. - - job_name: 'kubernetes-pods' - - kubernetes_sd_configs: - - role: pod - - relabel_configs: - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] - action: keep - regex: true - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] - action: replace - regex: (.+):(?:\d+);(\d+) - replacement: ${1}:${2} - target_label: __address__ - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_pod_name] - action: replace - target_label: kubernetes_pod_name - -networkPolicy: - ## Enable creation of NetworkPolicy resources. - ## - enabled: false diff --git a/charts/trigger-quay-builds/.helmignore b/charts/trigger-quay-builds/.helmignore deleted file mode 100644 index f0c131944..000000000 --- a/charts/trigger-quay-builds/.helmignore +++ /dev/null @@ -1,21 +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 -*~ -# Various IDEs -.project -.idea/ -*.tmproj diff --git a/charts/trigger-quay-builds/Chart.yaml b/charts/trigger-quay-builds/Chart.yaml deleted file mode 100644 index 82820d947..000000000 --- a/charts/trigger-quay-builds/Chart.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -description: A Helm chart for Kubernetes -name: trigger-quay-builds -version: 0.1.0 diff --git a/charts/trigger-quay-builds/templates/_helpers.tpl b/charts/trigger-quay-builds/templates/_helpers.tpl deleted file mode 100644 index 475d86985..000000000 --- a/charts/trigger-quay-builds/templates/_helpers.tpl +++ /dev/null @@ -1,16 +0,0 @@ -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} -{{- define "trigger_quay_builds.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -*/}} -{{- define "trigger_quay_builds.fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} diff --git a/charts/trigger-quay-builds/templates/cronjob.yaml b/charts/trigger-quay-builds/templates/cronjob.yaml deleted file mode 100644 index 2270dc637..000000000 --- a/charts/trigger-quay-builds/templates/cronjob.yaml +++ /dev/null @@ -1,27 +0,0 @@ -apiVersion: batch/v2alpha1 -kind: CronJob -metadata: - name: {{ template "trigger_quay_builds.fullname" . }} -spec: - schedule: {{ .Values.schedule | quote }} - jobTemplate: - spec: - template: - spec: - containers: - - name: trigger-quay-builds - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} - imagePullPolicy: Always - env: - - name: REPOSITORY - value: {{ .Values.REPOSITORY }} - - name: TRIGGER_UUID - value: {{ .Values.TRIGGER_UUID }} - - name: ROBOT_TOKEN - valueFrom: - secretKeyRef: - name: {{ template "trigger_quay_builds.fullname" . }} - key: ROBOT_TOKEN - restartPolicy: OnFailure - - diff --git a/charts/trigger-quay-builds/templates/secret.yaml b/charts/trigger-quay-builds/templates/secret.yaml deleted file mode 100644 index 3f3324823..000000000 --- a/charts/trigger-quay-builds/templates/secret.yaml +++ /dev/null @@ -1,6 +0,0 @@ -kind: Secret -apiVersion: v1 -metadata: - name: {{ template "trigger_quay_builds.fullname" . }} -data: - ROBOT_TOKEN: {{ .Values.ROBOT_TOKEN | b64enc }} \ No newline at end of file diff --git a/charts/trigger-quay-builds/values.yaml b/charts/trigger-quay-builds/values.yaml deleted file mode 100644 index e4793d8a2..000000000 --- a/charts/trigger-quay-builds/values.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Default values for trigger_quay_builds. - -image: - repository: desdrury/quay_build - tag: latest - pullPolicy: Always - -REPOSITORY: XXXX -TRIGGER_UUID: XXXX -ROBOT_TOKEN: XXXX -schedule: "*/5 * * * *" \ No newline at end of file diff --git a/cli/.babelrc.js b/cli/.babelrc.js deleted file mode 100644 index 31310f269..000000000 --- a/cli/.babelrc.js +++ /dev/null @@ -1,29 +0,0 @@ -const { - engines: { node }, -} = require('./package.json'); - -module.exports = { - comments: false, - presets: [ - [ - '@babel/env', - { - targets: { - node: node.substring(2), // Strip `>=` - }, - shippedProposals: true, - modules: process.env.MODULE ? false : 'commonjs', - useBuiltIns: 'usage', - }, - ], - ], - plugins: [ - '@babel/transform-flow-strip-types', - [ - '@babel/transform-runtime', - { - regenerator: false, - }, - ], - ], -}; diff --git a/cli/.eslintignore b/cli/.eslintignore deleted file mode 100644 index 7e3630743..000000000 --- a/cli/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -build/ -flow-typed/ diff --git a/cli/.eslintrc.js b/cli/.eslintrc.js deleted file mode 100644 index 96000b1b5..000000000 --- a/cli/.eslintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('eslint-config-lagoon-node'); diff --git a/cli/.gitignore b/cli/.gitignore deleted file mode 100644 index c88637515..000000000 --- a/cli/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules/ -build/ -.npmrc -.DS_Store -.lagoon.yml -npm-debug.log* diff --git a/cli/.projectile b/cli/.projectile deleted file mode 100644 index e69de29bb..000000000 diff --git a/cli/.yarnrc b/cli/.yarnrc deleted file mode 100644 index a77d033f2..000000000 --- a/cli/.yarnrc +++ /dev/null @@ -1 +0,0 @@ ---run.silent true \ No newline at end of file diff --git a/cli/10-ssh-agent.sh b/cli/10-ssh-agent.sh deleted file mode 100644 index 3fa2838d9..000000000 --- a/cli/10-ssh-agent.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -set -e - -# If we there is an ssh key injected via lagoon and kubernetes, we use that -if [ ! -z "$SSH_PRIVATE_KEY" ]; then - echo -e "$SSH_PRIVATE_KEY" > /home/.ssh/id_rsa -fi - diff --git a/cli/Dockerfile b/cli/Dockerfile deleted file mode 100644 index f835e891e..000000000 --- a/cli/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -ARG LAGOON_GIT_BRANCH -ARG IMAGE_REPO -# STAGE 1: Loading Image lagoon-node-packages-builder which contains node packages shared by all Node Services -FROM ${IMAGE_REPO:-amazeeiolagoon}/yarn-workspace-builder:${LAGOON_GIT_BRANCH:-latest} as yarn-workspace-builder - -# STAGE 2: specific service Image -FROM ${IMAGE_REPO:-amazeeiolagoon}/node:8 - -RUN apk add --no-cache bash \ - && mkdir -p /home/.ssh \ - && fix-permissions /home/ - -# Copying generated node_modules from the first stage -COPY --from=yarn-workspace-builder /app /app - -# Setting the workdir to the service, all following commands will run from here -WORKDIR /app/cli/ - -# Copying the .env.defaults into the Workdir, as the dotenv system searches within the workdir for it -COPY --from=yarn-workspace-builder /app/.env.defaults . - -# Copying files from our service -COPY . . - -# Verify that all dependencies have been installed via the yarn-workspace-builder -RUN yarn check --verify-tree - -# Making sure we run in production -ENV NODE_ENV production - -COPY 10-ssh-agent.sh /lagoon/entrypoints/ - -CMD ["/bin/docker-sleep"] \ No newline at end of file diff --git a/cli/README.md b/cli/README.md deleted file mode 100644 index 753cd63db..000000000 --- a/cli/README.md +++ /dev/null @@ -1,142 +0,0 @@ -# lagu - -> lagoon Command Line Interface - -## Installation - -Install the CLI with either `npm` or `yarn`. - -```sh -# Either npm... -npm install --global @lagoon/lagu - -# ...or Yarn -yarn global add @lagoon/lagu -``` - -## Setup - -The CLI needs a configuration file at `/.lagoon.yml`, which can be created with [the `init` command](#lagu-init): - -```sh -# Initialize project configuration -$ lagu init -``` - -For more options, see the [`lagu init` documentation](#lagu-init). - -## Commands - -### `lagu init` - -```text -$ lagu init --help -lagu init - Create a .lagoon.yml config file in the current working directory - -Options: - --version Show version number [boolean] - --help Show help [boolean] - --overwrite Overwrite the configuration file if it exists [boolean] - --project Name of project to configure [string] - -Examples: - lagu init Create a config file at - ./.lagoon.yml. This will confirm - with the user whether to overwrite - the config if it already exists and - also prompt for a project name to - add to the config. - - lagu init --overwrite Overwrite existing config file (do - not confirm with the user). - - lagu init --overwrite false Prevent overwriting of existing - config file (do not confirm with - user). - - lagu init --project my_project Set project to "my_project" (do not - prompt the user). - - lagu init --overwrite --project Overwrite existing config files and - my_project set project to "my_project" (do not - confirm with or prompt the user). -``` - -#### `lagu init` Examples - -```text -$ lagu init -? Enter the name of the project to configure. example -Creating file '/Users/you/git/.lagoon.yml'... -Configuration file created! -``` - -This will generate the following file: - -```text -$ cat .lagoon.yml -project: example -``` - -### `lagu login` - -```text -$ lagu login --help -lagu login - Authenticate with lagoon via an SSH key - -Options: - --version Show version number [boolean] - --help Show help [boolean] - --identity Path to identity (private key) [string] -``` - -#### `lagu login` Examples - -By default, the login command uses the SSH private key at `$HOME/.ssh/id_rsa`. - -```text -$ lagu login -Login successful -``` - -If that file does not exist, the user will be prompted for the path: - -```text -$ lagu login -? Path to private key file /path/to/id_rsa -Login successful -``` - -The path to the key can be also passed in via the `--identity` option: - -```text -$ lagu login --identity ./local-dev/id_ed25519 -Login successful -``` - -If the private key has a passphrase, the user will be prompted to enter it. The passphrase will never be saved. - -```text -$ lagu login --identity ./local-dev/id_ed25519 -? Private key passphrase (never saved) [hidden] -Login successful -``` - -## Development - docker - -- First build the cli image: `make build/cli` (dependencies are automatically build) -- Run the cli docker container via `docker-compose up -d cli` (dependencies are automatically started) -- Run a bash inside the container: `docker-compose exec cli bash` -- Use `yarn execute login` to login -- Now you can run commands via `yarn execute ` - -## Development - local nodejs - -The `execute ` yarn script can be used to run CLI commands during development. - -Additionally the following parameters should be set in the `.lagoon.yml` file. They can also be configured with the `init` command. - -```yaml -api: http://localhost:3000 -ssh: localhost:2020 -``` diff --git a/cli/bin/lagu.js b/cli/bin/lagu.js deleted file mode 100755 index 99b8899ac..000000000 --- a/cli/bin/lagu.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node - -const importLocal = require('import-local'); - -// Try using locally installed version and fall back to global version -const localImportFailed = !importLocal(__filename); - -if (localImportFailed) { - require('../build').run(); -} diff --git a/cli/jest.config.js b/cli/jest.config.js deleted file mode 100644 index 2ac9b1e2a..000000000 --- a/cli/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - rootDir: '.', - testPathIgnorePatterns: ['node_modules', '/build'], - transform: { - '^.+\\.jsx?$': 'babel-jest', - }, -}; diff --git a/cli/package.json b/cli/package.json deleted file mode 100644 index bb7121440..000000000 --- a/cli/package.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "name": "@lagoon/lagu", - "version": "4.0.0", - "description": "Lagoon Command Line Interface", - "main": "./bin/lagu.js", - "bin": { - "lagu": "./bin/lagu.js" - }, - "files": [ - "bin", - "build" - ], - "engines": { - "node": ">=8.12.0" - }, - "scripts": { - "prepublish": "in-publish && yarn run build || not-in-publish", - "preversion": "yarn test", - "version": "yarn run build", - "postversion": "git push && git push --tags", - "format": "prettier-eslint --write '**/*.js'", - "lint": "../node-packages/eslint-config-lagoon-node/node_modules/.bin/eslint .", - "test": "yarn run lint && jest", - "test:watch": "jest --watch", - "build": "rimraf build && babel src -d build", - "watch": "babel --watch=src -d build", - "execute": "bash -c 'node -r @babel/register ./scripts/execute.js $* $([[ $1 = login && ! $* =~ '--identity' ]] && echo \"--identity ../local-dev/cli_id_rsa\" || echo \"\")' -- " - }, - "repository": { - "type": "git", - "url": "git+https://github.com/amazeeio/lagoon.git" - }, - "author": "amazee.io (http://www.amazee.io)", - "contributors": [ - "Patrick Stapfer ", - "Karl Horky " - ], - "license": "MIT", - "bugs": { - "url": "https://github.com/amazeeio/lagoon/issues" - }, - "homepage": "https://github.com/amazeeio/lagoon#readme", - "devDependencies": { - "@babel/cli": "^7.0.0", - "@babel/core": "^7.0.1", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/preset-env": "^7.0.0", - "@babel/register": "^7.0.0", - "@lagoon/commons": "4.0.0", - "babel-core": "^7.0.0-0", - "babel-jest": "^23.6.0", - "dotenv-extended": "^2.0.2", - "jest": "^23.6.0", - "node-fetch": "^2.2.0", - "prettier": "^1.14.2", - "prettier-eslint-cli": "^4.7.1", - "rimraf": "^2.6.2" - }, - "dependencies": { - "@babel/runtime": "^7.0.0", - "camelcase-keys": "^4.2.0", - "chalk": "^2.4.1", - "csv-stringify": "^3.1.1", - "execa": "^0.10.0", - "exit": "^0.1.2", - "findup-sync": "^2.0.0", - "fuzzysearch": "^1.0.3", - "graphql": "^0.13.2", - "hosted-git-info": "^2.7.1", - "import-local": "^1.0.0", - "in-publish": "^2.0.0", - "inquirer": "^6.0.0", - "inquirer-autocomplete-prompt": "^1.0.1", - "js-yaml": "^3.12.0", - "ramda": "^0.25.0", - "strip-ansi": "^4.0.0", - "text-table": "^0.2.0", - "tildify": "^1.2.0", - "to-snake-case": "^1.0.0", - "untildify": "^3.0.3", - "url-regex": "^4.1.1", - "yargs": "^12.0.1" - } -} diff --git a/cli/scripts/execute.js b/cli/scripts/execute.js deleted file mode 100644 index 2c3334177..000000000 --- a/cli/scripts/execute.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node - -require('../src').run(); diff --git a/cli/src/__tests__/__snapshots__/e2e.test.js.snap b/cli/src/__tests__/__snapshots__/e2e.test.js.snap deleted file mode 100644 index b07781907..000000000 --- a/cli/src/__tests__/__snapshots__/e2e.test.js.snap +++ /dev/null @@ -1,145 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`lagu should create a project 1`] = ` -"! Set \\"customer\\" option to \\"3\\" from arguments or config -! Set \\"name\\" option to \\"e2e-test-project\\" from arguments or config -! Set \\"gitUrl\\" option to \\"ssh://git@192.168.99.1:2222/git/e2e-test-project.git\\" from arguments or config -! Set \\"openshift\\" option to \\"2\\" from arguments or config -! Set \\"branches\\" option to \\"true\\" from arguments or config -! Set \\"pullrequests\\" option to \\"true\\" from arguments or config -! Set \\"productionEnvironment\\" option to \\"master\\" from arguments or config -Project \\"e2e-test-project\\" created successfully: -Name e2e-test-project -Customer ci-customer -Git URL ssh://git@192.168.99.1:2222/git/e2e-test-project.git -Active Systems Deploy lagoon_openshiftBuildDeploy -Active Systems Remove lagoon_openshiftRemove -Branches true -Pull Requests true -Openshift ci-local -Created " -`; - -exports[`lagu should delete the project 1`] = `"Project \\"e2e-test-project\\" deleted successfully!"`; - -exports[`lagu should init 1`] = ` -"! Set \\"overwrite\\" option to \\"true\\" from arguments or config -! Set \\"project\\" option to \\"ci-github\\" from arguments or config -! Set \\"api\\" option to \\"http://localhost:3000\\" from arguments or config -! Set \\"ssh\\" option to \\"localhost:2020\\" from arguments or config -! Set \\"token\\" option to \\"/Users/k/p/lagoon/cli/src/__tests__/fixtures/.lagoon-token\\" from arguments or config -Creating file '/Users/k/p/lagoon/cli/src/__tests__/fixtures/.lagoon.yml'... -Configuration file created!" -`; - -exports[`lagu should list all environments for a project (project read from .lagoon.yml) 1`] = ` -"Name master -Environment Type production -Deploy Type branch -Created -Updated " -`; - -exports[`lagu should list all environments for a project (using --project option) 1`] = ` -"Name master -Environment Type production -Deploy Type branch -Created -Updated " -`; - -exports[`lagu should list all projects 1`] = ` -"Project Git URL Branches Pull Requests Created -ci-bitbucket ssh://git@192.168.99.1:2222/git/bitbucket.git true true -ci-drupal ssh://git@192.168.99.1:2222/git/drupal.git true true -ci-drupal-galera ssh://git@192.168.99.1:2222/git/drupal-galera.git true true -ci-drupal-postgres ssh://git@192.168.99.1:2222/git/drupal-postgres.git true true -ci-elasticsearch ssh://git@192.168.99.1:2222/git/elasticsearch.git true true -ci-env-limit ssh://git@192.168.99.1:2222/git/node.git true true -ci-features ssh://git@192.168.99.1:2222/git/features.git true true -ci-features-subfolder ssh://git@192.168.99.1:2222/git/features-subfolder.git true true -ci-github ssh://git@192.168.99.1:2222/git/github.git true true -ci-gitlab ssh://git@192.168.99.1:2222/git/gitlab.git true true -ci-multiproject1 ssh://git@192.168.99.1:2222/git/multiproject.git true true -ci-multiproject2 ssh://git@192.168.99.1:2222/git/multiproject.git true true -ci-nginx ssh://git@192.168.99.1:2222/git/nginx.git true true -ci-node ssh://git@192.168.99.1:2222/git/node.git true true -ci-rest ssh://git@192.168.99.1:2222/git/rest.git true true " -`; - -exports[`lagu should list no environments for a project with none (using --project option) 1`] = `"Name Environment Type Deploy Type Created Updated"`; - -exports[`lagu should list the new project among all projects 1`] = ` -"Project Git URL Branches Pull Requests Created -ci-bitbucket ssh://git@192.168.99.1:2222/git/bitbucket.git true true -ci-drupal ssh://git@192.168.99.1:2222/git/drupal.git true true -ci-drupal-galera ssh://git@192.168.99.1:2222/git/drupal-galera.git true true -ci-drupal-postgres ssh://git@192.168.99.1:2222/git/drupal-postgres.git true true -ci-elasticsearch ssh://git@192.168.99.1:2222/git/elasticsearch.git true true -ci-env-limit ssh://git@192.168.99.1:2222/git/node.git true true -ci-features ssh://git@192.168.99.1:2222/git/features.git true true -ci-features-subfolder ssh://git@192.168.99.1:2222/git/features-subfolder.git true true -ci-github ssh://git@192.168.99.1:2222/git/github.git true true -ci-gitlab ssh://git@192.168.99.1:2222/git/gitlab.git true true -ci-multiproject1 ssh://git@192.168.99.1:2222/git/multiproject.git true true -ci-multiproject2 ssh://git@192.168.99.1:2222/git/multiproject.git true true -ci-nginx ssh://git@192.168.99.1:2222/git/nginx.git true true -ci-node ssh://git@192.168.99.1:2222/git/node.git true true -ci-rest ssh://git@192.168.99.1:2222/git/rest.git true true -e2e-test-project ssh://git@192.168.99.1:2222/git/e2e-test-project.git true true " -`; - -exports[`lagu should log an error for a non-existent project (using --project option) 1`] = `"No project 'non-existent-project' found."`; - -exports[`lagu should log in 1`] = ` -"Logging in to lagoon at lagoon@localhost:2020... -Logged in successfully." -`; - -exports[`lagu should log out when logged in 1`] = `"Logged out successfully."`; - -exports[`lagu should not error on logout when not logged in 1`] = `"Logged out successfully."`; - -exports[`lagu should not show deleted project details (using --project option) 1`] = `"No project 'e2e-test-project' found."`; - -exports[`lagu should show customer details (project read from .lagoon.yml) 1`] = ` -"Customer details for project 'ci-github': -Name ci-customer -Comment null -Deploy Private Key √ -Users 4, 5 -Created " -`; - -exports[`lagu should show customer details (using --project option) 1`] = ` -"Customer details for project 'ci-multiproject1': -Name ci-customer -Comment null -Deploy Private Key √ -Users 4, 5 -Created " -`; - -exports[`lagu should show newly-created project details (using --project option) 1`] = ` -"Name e2e-test-project -Customer ci-customer -Git URL ssh://git@192.168.99.1:2222/git/e2e-test-project.git -Active Systems Deploy lagoon_openshiftBuildDeploy -Active Systems Remove lagoon_openshiftRemove -Branches true -Pull Requests true -Openshift ci-local -Created " -`; - -exports[`lagu should show project details (read from .lagoon.yml) 1`] = ` -"Name ci-github -Customer ci-customer -Git URL ssh://git@192.168.99.1:2222/git/github.git -Active Systems Deploy lagoon_openshiftBuildDeploy -Active Systems Remove lagoon_openshiftRemove -Branches true -Pull Requests true -Openshift ci-local -Created " -`; diff --git a/cli/src/__tests__/e2e.test.js b/cli/src/__tests__/e2e.test.js deleted file mode 100644 index 469798d17..000000000 --- a/cli/src/__tests__/e2e.test.js +++ /dev/null @@ -1,238 +0,0 @@ -// @flow - -import fs from 'fs'; -import path from 'path'; -import R from 'ramda'; -import { sync as spawnSync } from 'execa'; - -const CLI_PATH = path.join(__dirname, '..', '..', 'bin', 'lagu.js'); -const cwd = path.join(__dirname, 'fixtures'); -const tokenPath = path.join(cwd, '.lagoon-token'); - -const stripCreatedDates = R.replace( - /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/g, - ' ', -); - -describe('lagu', () => { - it('should fail with error message without any arguments', async () => { - const results = spawnSync(CLI_PATH, [], { - cwd, - reject: false, - }); - expect(results.code).toBe(1); - expect(results.message).toMatch('Not enough non-option arguments'); - }); - - it('should init', async () => { - const results = spawnSync( - CLI_PATH, - [ - 'init', - '--overwrite', - '--token', - tokenPath, - '--project', - 'ci-github', - '--api', - 'http://localhost:3000', - '--ssh', - 'localhost:2020', - ], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(results.stdout).toMatchSnapshot(); - }); - - it('should not error on logout when not logged in', async () => { - const results = spawnSync(CLI_PATH, ['logout'], { - cwd, - }); - expect(results.code).toBe(0); - expect(results.stdout).toMatchSnapshot(); - }); - - it('should log in', async () => { - const results = spawnSync( - CLI_PATH, - [ - 'login', - '--identity', - path.join('..', '..', '..', '..', 'local-dev', 'cli_id_rsa'), - ], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(results.stdout).toMatchSnapshot(); - // Test whether token file has JWT header - const tokenHeader = R.compose( - R.nth(0), - R.split('.'), - )(fs.readFileSync(tokenPath, 'utf8')); - expect(tokenHeader).toMatch(/^eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9$/); - }); - - it('should show customer details (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['customer', '--project', 'ci-multiproject1'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should show customer details (project read from .lagoon.yml)', async () => { - const results = spawnSync(CLI_PATH, ['customer'], { - cwd, - }); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should list all environments for a project (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['environments', '--project', 'ci-github'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should list no environments for a project with none (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['environments', '--project', 'ci-multiproject1'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should log an error for a non-existent project (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['environments', '--project', 'non-existent-project'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should list all environments for a project (project read from .lagoon.yml)', async () => { - const results = spawnSync(CLI_PATH, ['environments'], { cwd }); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should show project details (read from .lagoon.yml)', async () => { - const results = spawnSync(CLI_PATH, ['project'], { - cwd, - }); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should list all projects', async () => { - const results = spawnSync(CLI_PATH, ['projects'], { - cwd, - }); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should create a project', async () => { - const results = spawnSync( - CLI_PATH, - [ - 'project', - 'create', - '--customer', - '3', - '--name', - 'e2e-test-project', - '--gitUrl', - 'ssh://git@192.168.99.1:2222/git/e2e-test-project.git', - '--openshift', - '2', - '--branches', - 'true', - '--pullrequests', - 'true', - '--productionEnvironment', - 'master', - ], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should show newly-created project details (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['project', '--project', 'e2e-test-project'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should list the new project among all projects', async () => { - const results = spawnSync(CLI_PATH, ['projects'], { - cwd, - }); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should delete the project', async () => { - const results = spawnSync( - CLI_PATH, - ['project', 'delete', '--project', 'e2e-test-project'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(results.stdout).toMatchSnapshot(); - }); - - it('should not show deleted project details (using --project option)', async () => { - const results = spawnSync( - CLI_PATH, - ['project', '--project', 'e2e-test-project'], - { - cwd, - }, - ); - expect(results.code).toBe(0); - expect(stripCreatedDates(results.stdout)).toMatchSnapshot(); - }); - - it('should log out when logged in', async () => { - const results = spawnSync(CLI_PATH, ['logout'], { - cwd, - }); - expect(results.code).toBe(0); - expect(results.stdout).toMatchSnapshot(); - }); -}); diff --git a/cli/src/__tests__/fixtures/.gitignore b/cli/src/__tests__/fixtures/.gitignore deleted file mode 100644 index ffce64e95..000000000 --- a/cli/src/__tests__/fixtures/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.lagoon-token \ No newline at end of file diff --git a/cli/src/__tests__/fixtures/.gitkeep b/cli/src/__tests__/fixtures/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/cli/src/cli/answerWithOption.js b/cli/src/cli/answerWithOption.js deleted file mode 100644 index 1ff8f304f..000000000 --- a/cli/src/cli/answerWithOption.js +++ /dev/null @@ -1,75 +0,0 @@ -// @flow - -import { blue } from 'chalk'; -import R from 'ramda'; - -import type { inquirer$Answers } from 'inquirer'; - -function notifyOptionUsed( - clog: typeof console.log, - option: string, - val: any, -): void { - clog( - `${blue('!')} Set "${option}" option to "${val}" from arguments or config`, - ); -} - -// Return a [predicate, transformer] pair for use with R.cond(). The predicate and transformer functions expect an object with an "options" property containing the options to use. -export function answerWithOptionIfSet({ - option, - answers, - notify, - clog, -}: { - option: string, - answers: inquirer$Answers, - notify?: boolean, - clog: typeof console.log, -}) { - return [ - (R.compose( - // Option is set - R.has(option), - R.prop('options'), - ): ({ options: Object }) => boolean), - (objectWithOptions: { options: Object }): false => { - // Assign option key in the answers object to option value and let the user know - const propVal = R.path(['options', option], objectWithOptions); - if (notify === true) { - notifyOptionUsed(clog, option, propVal); - } - - // $FlowFixMe Covariant property cannot be assigned - answers[option] = propVal; - return false; - }, - ]; -} - -// Return a function to use with the `when` option of the question object. -// https://github.com/SBoudrias/Inquirer.js/issues/517#issuecomment-288964496 -export function answerWithOptionIfSetOrPrompt({ - option, - options, - notify, - clog, -}: { - option: string, - options: Object, - notify?: boolean, - clog: typeof console.log, -}): inquirer$Answers => boolean { - return (answers: inquirer$Answers) => - R.ifElse( - // If the option exists, use it and let the user know... - ...answerWithOptionIfSet({ - option, - answers, - notify, - clog, - }), - // ...otherwise return true to prompt the user to manually enter the option - R.T, - )({ options }); -} diff --git a/cli/src/cli/promptUntilValidKeyPath.js b/cli/src/cli/promptUntilValidKeyPath.js deleted file mode 100644 index 5a85f1f5b..000000000 --- a/cli/src/cli/promptUntilValidKeyPath.js +++ /dev/null @@ -1,30 +0,0 @@ -// @flow - -import inquirer from 'inquirer'; -import untildify from 'untildify'; -import { fileExists } from '../util/fs'; -import { printErrors } from '../util/printErrors'; - -export async function promptUntilValidKeyPath( - cerr: typeof console.error, -): Promise { - const { privateKeyPath } = await inquirer.prompt([ - { - type: 'input', - name: 'privateKeyPath', - message: 'Path to private key file', - // TODO: Move the fileExists validation logic to this object under the validate key to fail earlier - }, - ]); - - if ( - !(await fileExists( - // Expand tilde characters in paths - untildify(privateKeyPath), - )) - ) { - printErrors(cerr, 'File does not exist at given path!'); - return promptUntilValidKeyPath(cerr); - } - return privateKeyPath; -} diff --git a/cli/src/cli/registerCommands.js b/cli/src/cli/registerCommands.js deleted file mode 100644 index 27e0cc06d..000000000 --- a/cli/src/cli/registerCommands.js +++ /dev/null @@ -1,26 +0,0 @@ -// @flow - -import yargs from 'yargs'; -import { setConfigForHandlers } from './setConfigForHandlers'; -import { printErrors } from '../util/printErrors'; -import { globalOptions } from '../config/globalOptions'; - -export function registerCommands() { - try { - // eslint-disable-next-line no-unused-expressions - yargs - .options(globalOptions) - // Use yargs.commandDir method to initialize a directory of commands - // Ref: https://github.com/yargs/yargs/blob/e87f4873012e3541325e7ec6dafb11a93b5717e0/docs/advanced.md#commanddirdirectory-opts - .commandDir('../commands', { visit: setConfigForHandlers }) - // Require entry of at least one command after `lagoon`, such as `lagoon login`. - // `lagoon` by itself has no assigned function at the moment. - .demandCommand() - // .strict(): Error out on non-demanded or non-described command line argument - // .argv: Get arguments as an object - .strict().argv; - } catch (err) { - const exitCode = printErrors(console.error, 'Uncaught error:', err); - process.exit(exitCode); - } -} diff --git a/cli/src/cli/setConfigForHandlers.js b/cli/src/cli/setConfigForHandlers.js deleted file mode 100644 index 25412a106..000000000 --- a/cli/src/cli/setConfigForHandlers.js +++ /dev/null @@ -1,70 +0,0 @@ -// @flow - -import exit from 'exit'; -import R from 'ramda'; -import { setConfig } from '../config'; -import { getCommandOptions } from '../util/getCommandOptions'; -import { printErrors } from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { Argv } from 'yargs'; -import type { CommandHandlerArgs } from '../types/Command'; - -export type CommandModule = { - command: string, - commandOptions: { [key: string]: string }, - dynamicOptionsKeys: Array, - description: string, - builder?: (yargs: Yargs) => Yargs, - handler: (handlerArgs: CommandHandlerArgs) => Promise, -}; - -const cwd = process.cwd(); - -// Use the visit option (of `node-require-directory`) to provide a visitor function -// Ref: https://github.com/yargs/yargs/blob/0942a1518aad77656c135439194f8f825bd8b33a/test/command.js#L570-L599 -// Ref (node-require-directory): https://github.com/troygoode/node-require-directory#visiting-objects-as-theyre-loaded -// Ref (node-require-directory): https://github.com/troygoode/node-require-directory/blob/f043664108f4a4cdb9a1c10e42268d6db754c855/test/test.js#L161-L171 -export function setConfigForHandlers(cmd: CommandModule) { - return JSON.stringify(cmd) === '{}' - ? // If the cmd module is an empty object, just return the object - cmd - : // If the cmd module isn't empty, modify the handler function by currying in some - // parameters that we need and providing fulfillment and rejection callback - // functions for the promise. - { - ...cmd, - handler: (argv: Argv): Promise => { - const config = setConfig({ - argv, - dynamicOptionsKeys: R.prop('dynamicOptionsKeys', cmd), - }); - - const options = getCommandOptions({ - config, - commandOptions: R.prop('commandOptions', cmd), - }); - - return ( - cmd - .handler({ - options, - cwd, - clog: console.log, - cerr: console.error, - }) - // On errors, log error and then exit with a failure exit code - .catch((err) => { - const exitCode = printErrors( - console.error, - `Uncaught error in ${cmd.command} command:`, - err, - ); - process.exit(exitCode); - }) - // Process returned with an exit code of typically 0 (success) or 1 (failure) - .then(code => exit(code)) - ); - }, - }; -} diff --git a/cli/src/commands/__tests__/__snapshots__/customer.test.js.snap b/cli/src/commands/__tests__/__snapshots__/customer.test.js.snap deleted file mode 100644 index 2136c3ce2..000000000 --- a/cli/src/commands/__tests__/__snapshots__/customer.test.js.snap +++ /dev/null @@ -1,35 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`handler should show customer details 1`] = ` -Array [ - Array [ - "Customer details for project 'some_project':", - ], - Array [ - "Name customer1 -Comment Comment about customer1 -Deploy Private Key √ -Users 0 -Created Wed May 18 2011 00:00:00 GMT+0000 (UTC)", - ], -] -`; - -exports[`handler should show error message if GraphQL returns errors 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "Something, something missing parameter X", - ], -] -`; - -exports[`handler should show message for non-existing projects 1`] = ` -Array [ - Array [ - "No customer found for project 'some_project'!", - ], -] -`; diff --git a/cli/src/commands/__tests__/__snapshots__/init.test.js.snap b/cli/src/commands/__tests__/__snapshots__/init.test.js.snap deleted file mode 100644 index a461ddcc9..000000000 --- a/cli/src/commands/__tests__/__snapshots__/init.test.js.snap +++ /dev/null @@ -1,58 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`handler should not overwrite config file when \`overwrite\` option set to false 1`] = ` -Array [ - Array [ - "Not overwriting existing file 'some/path/.lagoon.yml'.", - ], -] -`; - -exports[`handler should overwrite existing config file if overwrite option passed as true 1`] = ` -Array [ - Array [ - "! Set \\"overwrite\\" option to \\"true\\" from arguments or config", - ], - Array [ - "! Set \\"project\\" option to \\"test_project\\" from arguments or config", - ], - Array [ - "! Set \\"api\\" option to \\"\\" from arguments or config", - ], - Array [ - "! Set \\"ssh\\" option to \\"\\" from arguments or config", - ], - Array [ - "! Set \\"token\\" option to \\"\\" from arguments or config", - ], - Array [ - "Creating file 'some/path/.lagoon.yml'...", - ], - Array [ - "Configuration file created!", - ], -] -`; - -exports[`handler should write default yaml to given cwd + .lagoon.yml 1`] = ` -Array [ - Array [ - "! Set \\"project\\" option to \\"test_project\\" from arguments or config", - ], - Array [ - "! Set \\"api\\" option to \\"\\" from arguments or config", - ], - Array [ - "! Set \\"ssh\\" option to \\"\\" from arguments or config", - ], - Array [ - "! Set \\"token\\" option to \\"\\" from arguments or config", - ], - Array [ - "Creating file 'some/path/.lagoon.yml'...", - ], - Array [ - "Configuration file created!", - ], -] -`; diff --git a/cli/src/commands/__tests__/__snapshots__/project.test.js.snap b/cli/src/commands/__tests__/__snapshots__/project.test.js.snap deleted file mode 100644 index 73a3aedce..000000000 --- a/cli/src/commands/__tests__/__snapshots__/project.test.js.snap +++ /dev/null @@ -1,36 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`handler should display error, if GraphQL sends error messages 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "something something error", - ], -] -`; - -exports[`handler should show details for given project 1`] = ` -Array [ - Array [ - "Name credentialstest-project1 -Customer credentialtest-customer1 -Git URL project1.git -Active Systems Deploy lagoon_openshiftBuildDeploy -Active Systems Remove lagoon_openshiftRemove -Branches true -Pull Requests null -Openshift credentialtest-openshift -Created 2018-01-15 11:09:35", - ], -] -`; - -exports[`handler should show error on missing project 1`] = ` -Array [ - Array [ - "No project 'not_existing' found.", - ], -] -`; diff --git a/cli/src/commands/__tests__/__snapshots__/projects.test.js.snap b/cli/src/commands/__tests__/__snapshots__/projects.test.js.snap deleted file mode 100644 index 0a960d071..000000000 --- a/cli/src/commands/__tests__/__snapshots__/projects.test.js.snap +++ /dev/null @@ -1,89 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`handler should display error, if GraphQL sends error messages 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "something something error", - ], -] -`; - -exports[`handler should list details for multiple projects 1`] = ` -Array [ - Array [ - "Project Git URL Branches Pull Requests Created -credentialstest-project1 ssh://git@192.168.99.1:2222/git/project1.git true null 2018-01-15 11:09:35 -credentialstest-project2 ssh://git@192.168.99.1:2222/git/project2.git true null 2018-01-15 11:09:35", - ], -] -`; - -exports[`handler should list details for multiple projects in csv format 1`] = ` -Array [ - Array [ - "Project,Git URL,Branches,Pull Requests,Created -credentialstest-project1,ssh://git@192.168.99.1:2222/git/project1.git,true,null,2018-01-15 11:09:35 -credentialstest-project2,ssh://git@192.168.99.1:2222/git/project2.git,true,null,2018-01-15 11:09:35 -", - ], -] -`; - -exports[`handler should list details for multiple projects in json format 1`] = ` -Array [ - Array [ - Array [ - Array [ - "Project", - "Git URL", - "Branches", - "Pull Requests", - "Created", - ], - Array [ - "credentialstest-project1", - "ssh://git@192.168.99.1:2222/git/project1.git", - "true", - "null", - "2018-01-15 11:09:35", - ], - Array [ - "credentialstest-project2", - "ssh://git@192.168.99.1:2222/git/project2.git", - "true", - "null", - "2018-01-15 11:09:35", - ], - ], - ], -] -`; - -exports[`handler should list details for multiple projects in simple format 1`] = ` -Array [ - Array [ - "Project: credentialstest-project1 -Git URL: ssh://git@192.168.99.1:2222/git/project1.git -Branches: true -Pull Requests: null -Created: 2018-01-15 11:09:35 - -Project: credentialstest-project2 -Git URL: ssh://git@192.168.99.1:2222/git/project2.git -Branches: true -Pull Requests: null -Created: 2018-01-15 11:09:35", - ], -] -`; - -exports[`handler should print notice on empty projects array 1`] = ` -Array [ - Array [ - "No projects found.", - ], -] -`; diff --git a/cli/src/commands/__tests__/customer.test.js b/cli/src/commands/__tests__/customer.test.js deleted file mode 100644 index c9878c34e..000000000 --- a/cli/src/commands/__tests__/customer.test.js +++ /dev/null @@ -1,104 +0,0 @@ -// @flow - -import { queryGraphQL } from '../../util/queryGraphQL'; -import { handler } from '../customer'; - -jest.mock('../../util/queryGraphQL'); -jest.mock('../../config', () => ({ - getConfig: jest.fn(() => ({ format: 'table' })), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -const mockResponse = { - data: { - projectByName: { - customer: { - name: 'customer1', - comment: 'Comment about customer1', - privateKey: 'PRIVATE_KEY', - users: [ - { - id: 0, - }, - ], - created: 'Wed May 18 2011 00:00:00 GMT+0000 (UTC)', - }, - }, - }, -}; - -describe('handler', () => { - it('should show customer details', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve(mockResponse), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'some_project', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should show error message if GraphQL returns errors', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - errors: [{ message: 'Something, something missing parameter X' }], - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'some_project', - }, - }); - - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should show message for non-existing projects', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({}), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'some_project', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/commands/__tests__/init.test.js b/cli/src/commands/__tests__/init.test.js deleted file mode 100644 index 386142171..000000000 --- a/cli/src/commands/__tests__/init.test.js +++ /dev/null @@ -1,96 +0,0 @@ -// @flow - -import { fileExists } from '../../util/fs'; -import { handler } from '../init'; - -jest.mock('fs'); -jest.mock('../../config'); -jest.mock('../../util/fs'); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -describe('handler', () => { - // TODO: Also write a test where it bails - it('should overwrite existing config file if overwrite option passed as true', async () => { - _castMockForFlow(fileExists).mockImplementationOnce(() => - Promise.resolve(true), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - const cwd = 'some/path'; - - const code = await handler({ - clog, - cerr, - cwd, - options: { - format: 'table', - overwrite: true, - project: 'test_project', - api: '', - ssh: '', - token: '', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should not overwrite config file when `overwrite` option set to false', async () => { - _castMockForFlow(fileExists).mockImplementationOnce(() => - Promise.resolve(true), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - const cwd = 'some/path'; - - const code = await handler({ - clog, - cerr, - cwd, - options: { - format: 'table', - overwrite: false, - project: 'test_project', - api: '', - ssh: '', - token: '', - }, - }); - - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should write default yaml to given cwd + .lagoon.yml', async () => { - _castMockForFlow(fileExists).mockImplementationOnce(() => - Promise.resolve(false), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - const cwd = 'some/path'; - - const code = await handler({ - clog, - cerr, - cwd, - options: { - format: 'table', - overwrite: false, - project: 'test_project', - api: '', - ssh: '', - token: '', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/commands/__tests__/project.test.js b/cli/src/commands/__tests__/project.test.js deleted file mode 100644 index 98ebbfcad..000000000 --- a/cli/src/commands/__tests__/project.test.js +++ /dev/null @@ -1,108 +0,0 @@ -// @flow - -import { queryGraphQL } from '../../util/queryGraphQL'; -import { handler } from '../project'; - -jest.mock('../../util/queryGraphQL'); -jest.mock('../../config', () => ({ - getConfig: jest.fn(() => ({ format: 'table' })), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -const mockErrorResponse = { - errors: [{ message: 'something something error' }], -}; - -describe('handler', () => { - const mockResponse1 = { - data: { - projectByName: { - name: 'credentialstest-project1', - customer: { - name: 'credentialtest-customer1', - }, - gitUrl: 'project1.git', - activeSystemsDeploy: 'lagoon_openshiftBuildDeploy', - activeSystemsRemove: 'lagoon_openshiftRemove', - branches: 'true', - pullrequests: 'null', - openshift: { - name: 'credentialtest-openshift', - }, - created: '2018-01-15 11:09:35', - }, - }, - }; - - it('should display error, if GraphQL sends error messages', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve(mockErrorResponse), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'some_project', - }, - }); - - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should show error on missing project', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({}), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'not_existing', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should show details for given project', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve(mockResponse1), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - project: 'myproject', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/commands/__tests__/projects.test.js b/cli/src/commands/__tests__/projects.test.js deleted file mode 100644 index 8fd44224b..000000000 --- a/cli/src/commands/__tests__/projects.test.js +++ /dev/null @@ -1,238 +0,0 @@ -// @flow - -import { getConfig } from '../../config'; -import { queryGraphQL } from '../../util/queryGraphQL'; -import { handler } from '../projects'; - -jest.mock('../../util/queryGraphQL'); -jest.mock('../../config', () => ({ - getConfig: jest.fn(() => ({ format: 'table' })), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -describe('handler', () => { - it('should list details for multiple projects', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allProjects: [ - { - name: 'credentialstest-project1', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - { - name: 'credentialstest-project2', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project2.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - ], - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should list details for multiple projects in json format', async () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'json', - })); - - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allProjects: [ - { - name: 'credentialstest-project1', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - { - name: 'credentialstest-project2', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project2.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - ], - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'json', - token: 'token/path', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should list details for multiple projects in csv format', async () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'csv', - })); - - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allProjects: [ - { - name: 'credentialstest-project1', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - { - name: 'credentialstest-project2', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project2.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - ], - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'csv', - token: 'token/path', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should list details for multiple projects in simple format', async () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'simple', - })); - - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allProjects: [ - { - name: 'credentialstest-project1', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - { - name: 'credentialstest-project2', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project2.git', - branches: 'true', - pullrequests: null, - created: '2018-01-15 11:09:35', - }, - ], - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'simple', - token: 'token/path', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should print notice on empty projects array', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve([]), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(code).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it('should display error, if GraphQL sends error messages', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - errors: [{ message: 'something something error' }], - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const code = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/commands/customer.js b/cli/src/commands/customer.js deleted file mode 100644 index 20993de85..000000000 --- a/cli/src/commands/customer.js +++ /dev/null @@ -1,114 +0,0 @@ -// @flow - -import { red } from 'chalk'; -import R from 'ramda'; -import format from '../util/format'; -import gql from '../util/gql'; -import { queryGraphQL } from '../util/queryGraphQL'; -import { - printProjectConfigurationError, - printGraphQLErrors, -} from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgsWithOptions } from '../types/Command'; - -export const command = 'customer'; -export const description = 'Show customer details for a given project name'; - -const PROJECT: 'project' = 'project'; - -export const commandOptions = { - [PROJECT]: PROJECT, -}; - -export function builder(yargs: Yargs) { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [PROJECT]: { - demandOption: false, - describe: 'Specify a project for the customer', - type: 'string', - }, - }) - .example( - `$0 ${command}`, - 'Show customer details for the project configured in .lagoon.yml', - ) - .example( - `$0 ${command} --${PROJECT} myproject`, - 'Show customer details for the project "myproject"', - ); -} - -type Args = CommandHandlerArgsWithOptions<{ - +project?: string, -}>; - -export async function handler({ - options: { project }, - clog, - cerr, -}: -Args): Promise { - if (project == null) { - return printProjectConfigurationError(cerr); - } - - const result = await queryGraphQL({ - cerr, - query: gql` - query CustomerByProjectName($project: String!) { - projectByName(name: $project) { - customer { - name - comment - privateKey - users { - id - } - created - } - } - } - `, - variables: { project }, - }); - - const { errors } = result; - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - const customer = R.path(['data', 'projectByName', 'customer'], result); - - if (customer == null) { - clog(red(`No customer found for project '${project}'!`)); - return 0; - } - - const convertPrivateKeyToSymbol = R.ifElse( - R.identity, - R.always('\u221A'), // √ - R.always('\u2717'), // ✗ - ); - - const formatUsers: (Array) => Array = R.map(R.prop('id')); - - clog(`Customer details for project '${project}':`); - clog( - format([ - ['Name', 'Comment', 'Deploy Private Key', 'Users', 'Created'], - [ - R.prop('name', customer), - String(R.prop('comment', customer)), - convertPrivateKeyToSymbol(R.prop('privateKey', customer)), - R.join(', ', formatUsers(R.propOr([], 'users')(customer))), - R.prop('created', customer), - ], - ]), - ); - - return 0; -} diff --git a/cli/src/commands/environments.js b/cli/src/commands/environments.js deleted file mode 100644 index 0a4819358..000000000 --- a/cli/src/commands/environments.js +++ /dev/null @@ -1,112 +0,0 @@ -// @flow - -import R from 'ramda'; -import format from '../util/format'; -import gql from '../util/gql'; -import { queryGraphQL } from '../util/queryGraphQL'; -import { - printGraphQLErrors, - printProjectConfigurationError, -} from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgsWithOptions } from '../types/Command'; - -export const command = 'environments'; -export const description = 'Show environment details for a given project'; - -const PROJECT: 'project' = 'project'; - -export const commandOptions = { - [PROJECT]: PROJECT, -}; - -export function builder(yargs: Yargs): Yargs { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [PROJECT]: { - demandOption: false, - describe: 'Name of project', - type: 'string', - }, - }) - .example( - `$0 ${command}`, - 'Show environments for the project configured in .lagoon.yml', - ) - .example( - `$0 ${command} --${PROJECT} myproject`, - 'Show environments of project "myproject"', - ); -} - -type Args = CommandHandlerArgsWithOptions<{ - +project?: string, -}>; - -export async function handler({ - options: { project: projectName }, - clog, - cerr, -}: -Args): Promise { - if (projectName == null) { - return printProjectConfigurationError(cerr); - } - - const result = await queryGraphQL({ - cerr, - query: gql` - query ProjectByName($project: String!) { - projectByName(name: $project) { - environments { - name - environmentType - deployType - created - updated - } - } - } - `, - variables: { project: projectName }, - }); - - const { errors } = result; - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - const project = R.path(['data', 'projectByName'])(result); - - if (project == null) { - clog(`No project '${projectName}' found.`); - return 0; - } - - const environments = R.path(['environments'])(project); - - if (environments == null) { - clog(`No environments for project '${projectName}' found.`); - return 0; - } - - clog( - format([ - ['Name', 'Environment Type', 'Deploy Type', 'Created', 'Updated'], - ...R.map( - environment => [ - R.prop('name', environment), - R.prop('environmentType', environment), - R.prop('deployType', environment), - R.prop('created', environment), - R.prop('updated', environment), - ], - environments, - ), - ]), - ); - - return 0; -} diff --git a/cli/src/commands/init.js b/cli/src/commands/init.js deleted file mode 100644 index 3dd8a8907..000000000 --- a/cli/src/commands/init.js +++ /dev/null @@ -1,252 +0,0 @@ -// @flow - -import path from 'path'; -import { green } from 'chalk'; -import inquirer from 'inquirer'; -import R from 'ramda'; -import tildify from 'tildify'; -import untildify from 'untildify'; -import { answerWithOptionIfSetOrPrompt } from '../cli/answerWithOption'; -import { globalOptionDefaults } from '../config/globalOptions'; -import { writeConfigFile } from '../configFile/writeConfigFile'; -import { fileExists } from '../util/fs'; -import { printErrors } from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { ConfigFileInput } from '../types/ConfigFile'; -import type { CommandHandlerArgsWithOptions } from '../types/Command'; - -export const command = 'init'; -export const description = - 'Create a .lagoon.yml config file in the current working directory'; - -export const OVERWRITE: 'overwrite' = 'overwrite'; -export const PROJECT: 'project' = 'project'; -export const API: 'api' = 'api'; -export const SSH: 'ssh' = 'ssh'; -export const TOKEN: 'token' = 'token'; - -export const commandOptions = Object.freeze({ - [OVERWRITE]: OVERWRITE, - [PROJECT]: PROJECT, - [API]: API, - [SSH]: SSH, - [TOKEN]: TOKEN, -}); - -export const dynamicOptionsKeys = Object.freeze([ - OVERWRITE, - PROJECT, - API, - SSH, - TOKEN, -]); - -type OptionalOptions = { - overwrite?: boolean, - project?: string, - api?: string, - ssh?: string, - token: string, -}; - -export function builder(yargs: Yargs) { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [OVERWRITE]: { - describe: 'Overwrite the configuration file if it exists', - type: 'boolean', - }, - [PROJECT]: { - describe: 'Name of project to configure', - type: 'string', - }, - [API]: { - describe: 'API URL', - type: 'string', - }, - [SSH]: { - describe: 'SSH URL', - type: 'string', - }, - [TOKEN]: { - describe: 'Path to the Lagoon token file', - type: 'string', - }, - }) - .example( - `$0 ${command}`, - 'Create a config file at ./.lagoon.yml. This will confirm with the user whether to overwrite the config if it already exists and also prompt for some parameters to add to the config.\n', - ) - .example( - `$0 ${command} --${OVERWRITE}`, - 'Overwrite existing config file (do not confirm with the user).\n', - ) - .example( - `$0 ${command} --${OVERWRITE} false`, - 'Prevent overwriting of existing config file (do not confirm with user).\n', - ) - .example( - `$0 ${command} --${PROJECT} my_project`, - 'Set project to "my_project" (do not prompt the user).\n', - ) - .example( - `$0 ${command} --${API} http://localhost:3000`, - 'Set API URL to "http://localhost:3000" (do not prompt the user).\n', - ) - .example( - `$0 ${command} --${SSH} localhost:2020`, - 'Set SSH URL to "localhost:2020" (do not prompt the user).\n', - ) - .example( - `$0 ${command} --${TOKEN} ~/tokens/.lagoon-token`, - 'Set the token path to ~/tokens/.lagoon-token (do not prompt the user).\n', - ) - .example( - `$0 ${command} --${API} --${SSH} --${TOKEN}`, - 'Skip configuration of API and SSH URLs and token path (do not prompt the user).\n', - ) - .example( - `$0 ${command} --${OVERWRITE} --${PROJECT} my_project --${API} --${SSH} --${TOKEN}`, - 'Overwrite existing config files, set project to "my_project" and skip configuration of API and SSH URLs and token path (do not confirm with or prompt the user for any parameters).', - ); -} - -type PromptForOverwriteArgs = {| - filepath: string, - options: OptionalOptions, - clog: typeof console.log, -|}; - -async function promptForOverwrite({ - filepath, - options, - clog, -}: -PromptForOverwriteArgs): Promise<{ [key: typeof OVERWRITE]: boolean }> { - return inquirer.prompt([ - { - type: 'confirm', - name: OVERWRITE, - message: `File '${filepath}' already exists! Overwrite?`, - default: false, - when: answerWithOptionIfSetOrPrompt({ - option: OVERWRITE, - options, - notify: true, - clog, - }), - }, - ]); -} - -type Args = CommandHandlerArgsWithOptions<{ - +overwrite?: boolean, - +project?: string, -}>; - -export async function handler({ - cwd, - options, - clog, - cerr, -}: -Args): Promise { - const filepath = path.join(cwd, '.lagoon.yml'); - const exists = await fileExists(filepath); - - const overwrite = !exists - ? undefined - : R.prop( - OVERWRITE, - await promptForOverwrite({ - filepath, - options, - clog, - }), - ); - - if (exists && !overwrite) { - return printErrors(cerr, { - message: `Not overwriting existing file '${filepath}'.`, - }); - } - - const defaultToken = R.prop(TOKEN, globalOptionDefaults); - - // $FlowFixMe inquirer$Answers is inexact, LagoonConfigInput is exact - const configInput: ConfigFileInput = await inquirer.prompt([ - { - type: 'input', - name: PROJECT, - message: 'Enter the name of the project to configure.', - validate: input => (input ? Boolean(input) : 'Please enter a project.'), - when: answerWithOptionIfSetOrPrompt({ - option: PROJECT, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: API, - message: 'Enter the API URL', - when: answerWithOptionIfSetOrPrompt({ - option: API, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: SSH, - message: 'Enter the SSH URL', - when: answerWithOptionIfSetOrPrompt({ - option: SSH, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: TOKEN, - message: `Change the path for the token (default: ${R.compose( - tildify, - R.prop(TOKEN), - )(globalOptionDefaults)})`, - when: answerWithOptionIfSetOrPrompt({ - option: TOKEN, - options: (R.pickBy((val, key) => - // Filter to options that... - R.or( - // ...either don't have the key TOKEN... - R.complement(R.equals)(TOKEN, key), - // ...or those that are a TOKEN that are the default value. - // This is to avoid writing the default value in the config file. - R.complement(R.equals)(defaultToken, val), - ), - )(options): { ...typeof options }), - notify: true, - clog, - }), - filter: untildify, - }, - ]); - - try { - clog(`Creating file '${filepath}'...`); - await writeConfigFile(filepath, configInput); - clog(green('Configuration file created!')); - return 0; - } catch (e) { - return printErrors( - cerr, - `Error occurred while creating config at ${filepath}:`, - e, - ); - } -} diff --git a/cli/src/commands/login.js b/cli/src/commands/login.js deleted file mode 100644 index 306d150ff..000000000 --- a/cli/src/commands/login.js +++ /dev/null @@ -1,67 +0,0 @@ -// @flow - -import { green } from 'chalk'; -import { getSshConfig } from '../config/getSshConfig'; -import { runSshCommand } from '../util/runSshCommand'; -import { writeFile } from '../util/fs'; -import { printErrors } from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgsWithOptions } from '../types/Command'; - -export const command = 'login'; -export const description = 'Authenticate with lagoon via an SSH key'; - -const IDENTITY: 'identity' = 'identity'; -const TOKEN: 'token' = 'token'; - -export const commandOptions = { - [IDENTITY]: IDENTITY, - [TOKEN]: TOKEN, -}; - -export function builder(yargs: Yargs) { - return yargs.usage(`$0 ${command} - ${description}`).options({ - identity: { - describe: 'Path to identity (private key)', - type: 'string', - }, - }); -} - -type Args = CommandHandlerArgsWithOptions<{ - +identity: string, - +token: string, -}>; - -export async function handler({ - clog, - cerr, - options: { identity, token: tokenFilePath }, -}: -Args): Promise { - const { username, host, port } = getSshConfig(); - - console.log(`Logging in to lagoon at ${username}@${host}:${port}...`); - - let token; - - try { - token = await runSshCommand({ command: 'token', identity }); - } catch (err) { - return printErrors(cerr, err); - } - - if (!token) { - return printErrors( - cerr, - 'Empty token returned from Lagoon authentication server.', - ); - } - - await writeFile(tokenFilePath, token); - - clog(green('Logged in successfully.')); - - return 0; -} diff --git a/cli/src/commands/logout.js b/cli/src/commands/logout.js deleted file mode 100644 index 9ff98568c..000000000 --- a/cli/src/commands/logout.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow - -import { green } from 'chalk'; -import { fileExists, unlink } from '../util/fs'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgs } from '../types/Command'; - -export const command = 'logout'; -export const description = 'Delete the authentication token'; - -const TOKEN: 'token' = 'token'; - -export const commandOptions = { - [TOKEN]: TOKEN, -}; - -export function builder(yargs: Yargs) { - return yargs.usage(`$0 ${command} - ${description}`); -} - -export async function handler({ - clog, - options: { token: tokenFilePath }, -}: -CommandHandlerArgs): Promise { - if (tokenFilePath && (await fileExists(tokenFilePath))) { - await unlink(tokenFilePath); - } - - clog(green('Logged out successfully.')); - - return 0; -} diff --git a/cli/src/commands/project.js b/cli/src/commands/project.js deleted file mode 100644 index 6952db558..000000000 --- a/cli/src/commands/project.js +++ /dev/null @@ -1,147 +0,0 @@ -// @flow - -import inquirer from 'inquirer'; -import R from 'ramda'; -import { answerWithOptionIfSetOrPrompt } from '../cli/answerWithOption'; -import { setConfigForHandlers } from '../cli/setConfigForHandlers'; -import format from '../util/format'; -import gql from '../util/gql'; -import { queryGraphQL } from '../util/queryGraphQL'; -import { printGraphQLErrors } from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgsWithOptions } from '../types/Command'; - -export const command = 'project'; -export const description = 'Show project details'; - -export const PROJECT: 'project' = 'project'; - -export const commandOptions = { - [PROJECT]: PROJECT, -}; - -type OptionalOptions = { - project?: string, -}; - -type Options = { - +project: string, -}; - -export function builder(yargs: Yargs): Yargs { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [PROJECT]: { - demandOption: false, - describe: 'Name of project', - type: 'string', - }, - }) - .example( - `$0 ${command}`, - 'Show details for the project configured in .lagoon.yml', - ) - .example( - `$0 ${command} --${PROJECT} myproject`, - 'Show details of project "myproject"', - ) - .commandDir('projectCommands', { visit: setConfigForHandlers }); -} - -type PromptForQueryOptionsArgs = {| - options: OptionalOptions, - clog: typeof console.log, -|}; - -async function promptForQueryOptions({ - options, - clog, -}: -PromptForQueryOptionsArgs): Promise { - return inquirer.prompt([ - { - type: 'input', - name: PROJECT, - message: 'Project name:', - when: answerWithOptionIfSetOrPrompt({ option: PROJECT, options, clog }), - }, - ]); -} - -type Args = CommandHandlerArgsWithOptions<{ - +project?: string, -}>; - -export async function handler({ clog, cerr, options }: Args): Promise { - const { project: projectName } = await promptForQueryOptions({ - options, - clog, - }); - - const result = await queryGraphQL({ - cerr, - query: gql` - query ProjectByName($project: String!) { - projectByName(name: $project) { - name - customer { - name - } - gitUrl - activeSystemsDeploy - activeSystemsRemove - branches - pullrequests - openshift { - name - } - created - } - } - `, - variables: { project: projectName }, - }); - - const { errors } = result; - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - const project = R.path(['data', 'projectByName'])(result); - - if (project == null) { - clog(`No project '${projectName}' found.`); - return 0; - } - - clog( - format([ - [ - 'Name', - 'Customer', - 'Git URL', - 'Active Systems Deploy', - 'Active Systems Remove', - 'Branches', - 'Pull Requests', - 'Openshift', - 'Created', - ], - [ - R.prop('name', project), - R.path(['customer', 'name'], project), - R.prop('gitUrl', project), - R.prop('activeSystemsDeploy', project), - R.prop('activeSystemsRemove', project), - R.prop('branches', project), - R.prop('pullrequests', project), - R.path(['openshift', 'name'], project), - R.path(['created'], project), - ], - ]), - ); - - return 0; -} diff --git a/cli/src/commands/projectCommands/__tests__/__snapshots__/project-create.test.js.snap b/cli/src/commands/projectCommands/__tests__/__snapshots__/project-create.test.js.snap deleted file mode 100644 index 3fdef1b2b..000000000 --- a/cli/src/commands/projectCommands/__tests__/__snapshots__/project-create.test.js.snap +++ /dev/null @@ -1,101 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getAllowedCustomersAndOpenshifts should return all customers and all openshifts 1`] = ` -Object { - "allCustomers": Array [ - Object { - "name": "credentialtest-customer1", - "value": 1, - }, - Object { - "name": "credentialtest-customer2", - "value": 2, - }, - ], - "allOpenshifts": Array [ - Object { - "name": "credentialtest-openshift", - "value": 1, - }, - ], - "errors": undefined, -} -`; - -exports[`handler should display error, if GraphQL response contains zero customers 1`] = ` -Array [ - Array [ - "No authorized customers found!", - ], -] -`; - -exports[`handler should display error, if GraphQL response contains zero openshifts but one customer 1`] = ` -Array [ - Array [ - "No authorized openshifts found!", - ], -] -`; - -exports[`handler should display error, if GraphQL sends error messages the first time it's called 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "something something error", - ], -] -`; - -exports[`handler should display error, if GraphQL sends error messages the second time it's called 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "something something error 2", - ], -] -`; - -exports[`handler should display table after successful project creation 1`] = ` -Array [ - Array [ - "! Set \\"customer\\" option to \\"1\\" from arguments or config", - ], - Array [ - "! Set \\"name\\" option to \\"test-project\\" from arguments or config", - ], - Array [ - "! Set \\"gitUrl\\" option to \\"ssh://git@192.168.99.1:2222/git/project1.git\\" from arguments or config", - ], - Array [ - "! Set \\"openshift\\" option to \\"1\\" from arguments or config", - ], - Array [ - "! Set \\"branches\\" option to \\"true\\" from arguments or config", - ], - Array [ - "! Set \\"pullrequests\\" option to \\"true\\" from arguments or config", - ], - Array [ - "! Set \\"productionEnvironment\\" option to \\"null\\" from arguments or config", - ], - Array [ - "Project \\"test-project\\" created successfully:", - ], - Array [ - "Name test-project -Customer credentialtest-customer1 -Git URL ssh://git@192.168.99.1:2222/git/project1.git -Active Systems Deploy lagoon_openshiftBuildDeploy -Active Systems Remove lagoon_openshiftRemove -Branches true -Pull Requests true -Openshift credentialtest-openshift -Created 2018-03-05 10:26:22", - ], -] -`; diff --git a/cli/src/commands/projectCommands/__tests__/project-create.test.js b/cli/src/commands/projectCommands/__tests__/project-create.test.js deleted file mode 100644 index c489d01fa..000000000 --- a/cli/src/commands/projectCommands/__tests__/project-create.test.js +++ /dev/null @@ -1,294 +0,0 @@ -// @flow - -import R from 'ramda'; -import { queryGraphQL } from '../../../util/queryGraphQL'; - -import { - CUSTOMER, - OPENSHIFT, - allOptionsSpecified, - commandOptions, - getAllowedCustomersAndOpenshifts, - handler, -} from '../create'; - -jest.mock('../../../util/queryGraphQL'); -jest.mock('../../../config', () => ({ - getConfig: jest.fn(() => ({ format: 'table' })), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -// Satisfy Flow types -const options = { - ...R.omit([CUSTOMER, OPENSHIFT], commandOptions), - [CUSTOMER]: 0, - [OPENSHIFT]: 0, -}; - -describe('allOptionsSpecified', () => { - it('should return true when all options are specified', () => { - const returnVal = allOptionsSpecified(options); - expect(returnVal).toBe(true); - }); - - it('should return true when all options and more are specified', () => { - const returnVal = allOptionsSpecified({ - ...options, - anotherOptionKey: 'anotherOptionValue', - }); - expect(returnVal).toBe(true); - }); - - it('should return false if not all options are specified', () => { - const returnVal = allOptionsSpecified({ - ...R.dissoc(R.head(R.keys(commandOptions)), commandOptions), - }); - expect(returnVal).toBe(false); - }); -}); - -describe('getAllowedCustomersAndOpenshifts', () => { - it('should return all customers and all openshifts', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allCustomers: [ - { - value: 1, - name: 'credentialtest-customer1', - }, - { - value: 2, - name: 'credentialtest-customer2', - }, - ], - allOpenshifts: [ - { - value: 1, - name: 'credentialtest-openshift', - }, - ], - }, - }), - ); - - const cerr = jest.fn(); - - const returnVal = await getAllowedCustomersAndOpenshifts(cerr); - - expect(R.prop('allCustomers', returnVal)).toHaveLength(2); - expect(R.prop('allOpenshifts', returnVal)).toHaveLength(1); - expect(returnVal).toMatchSnapshot(); - }); -}); - -describe('handler', () => { - it('should display table after successful project creation', async () => { - _castMockForFlow(queryGraphQL) - .mockImplementationOnce(() => - Promise.resolve({ - data: { - allCustomers: [ - { - value: 1, - name: 'credentialtest-customer1', - }, - { - value: 2, - name: 'credentialtest-customer2', - }, - ], - allOpenshifts: [ - { - value: 1, - name: 'credentialtest-openshift', - }, - ], - }, - }), - ) - .mockImplementationOnce(() => - Promise.resolve({ - data: { - addProject: { - id: 1, - name: 'test-project', - customer: { - name: 'credentialtest-customer1', - }, - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - activeSystemsDeploy: 'lagoon_openshiftBuildDeploy', - activeSystemsRemove: 'lagoon_openshiftRemove', - branches: 'true', - pullrequests: 'true', - productionEnvironment: 'null', - openshift: { - name: 'credentialtest-openshift', - }, - created: '2018-03-05 10:26:22', - }, - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const returnVal = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - customer: 1, - name: 'test-project', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - openshift: 1, - branches: 'true', - pullrequests: 'true', - productionEnvironment: 'null', - }, - }); - - expect(returnVal).toBe(0); - expect(clog.mock.calls).toMatchSnapshot(); - }); - - it("should display error, if GraphQL sends error messages the first time it's called", async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - errors: [{ message: 'something something error' }], - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const returnVal = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(returnVal).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it("should display error, if GraphQL sends error messages the second time it's called", async () => { - _castMockForFlow(queryGraphQL) - .mockImplementationOnce(() => - Promise.resolve({ - data: { - allCustomers: [ - { - value: 1, - name: 'credentialtest-customer1', - }, - { - value: 2, - name: 'credentialtest-customer2', - }, - ], - allOpenshifts: [ - { - value: 1, - name: 'credentialtest-openshift', - }, - ], - }, - }), - ) - .mockImplementationOnce(() => - Promise.resolve({ - errors: [{ message: 'something something error 2' }], - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const returnVal = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - customer: 1, - name: 'test-project', - gitUrl: 'ssh://git@192.168.99.1:2222/git/project1.git', - openshift: 1, - branches: 'true', - pullrequests: 'true', - productionEnvironment: 'null', - }, - }); - - expect(returnVal).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should display error, if GraphQL response contains zero customers', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { allCustomers: [], allOpenshifts: [] }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const returnVal = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(returnVal).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should display error, if GraphQL response contains zero openshifts but one customer', async () => { - _castMockForFlow(queryGraphQL).mockImplementationOnce(() => - Promise.resolve({ - data: { - allCustomers: [ - { - value: 1, - name: 'credentialtest-customer1', - }, - ], - allOpenshifts: [], - }, - }), - ); - - const clog = jest.fn(); - const cerr = jest.fn(); - - const returnVal = await handler({ - clog, - cerr, - cwd: 'some/path', - options: { - format: 'table', - token: 'token/path', - }, - }); - - expect(returnVal).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/commands/projectCommands/create.js b/cli/src/commands/projectCommands/create.js deleted file mode 100644 index 3c442a154..000000000 --- a/cli/src/commands/projectCommands/create.js +++ /dev/null @@ -1,465 +0,0 @@ -// @flow - -import { green, blue } from 'chalk'; -import fuzzysearch from 'fuzzysearch'; -import { fromUrl as hostedGitInfoFromUrl } from 'hosted-git-info'; -import inquirer from 'inquirer'; -import autocompletePrompt from 'inquirer-autocomplete-prompt'; -import R from 'ramda'; -import { - answerWithOptionIfSetOrPrompt, - answerWithOptionIfSet, -} from '../../cli/answerWithOption'; -import format from '../../util/format'; -import gql from '../../util/gql'; -import { printGraphQLErrors, printErrors } from '../../util/printErrors'; -import { queryGraphQL } from '../../util/queryGraphQL'; - -import typeof Yargs from 'yargs'; -import type { inquirer$Question } from 'inquirer'; -import type { CommandHandlerArgsWithOptions } from '../../types/Command'; - -// $FlowFixMe inquirer$PromptModule interface doesn't match autocompletePrompt module -inquirer.registerPrompt('autocomplete', autocompletePrompt); - -export const command = 'create'; -export const description = 'Create new project'; - -export const CUSTOMER: 'customer' = 'customer'; -export const NAME: 'name' = 'name'; -export const GIT_URL: 'gitUrl' = 'gitUrl'; -export const OPENSHIFT: 'openshift' = 'openshift'; -export const BRANCHES: 'branches' = 'branches'; -export const PULLREQUESTS: 'pullrequests' = 'pullrequests'; -export const PRODUCTION_ENVIRONMENT: 'productionEnvironment' = - 'productionEnvironment'; - -export const commandOptions = { - [CUSTOMER]: CUSTOMER, - [NAME]: NAME, - [GIT_URL]: GIT_URL, - [OPENSHIFT]: OPENSHIFT, - [BRANCHES]: BRANCHES, - [PULLREQUESTS]: PULLREQUESTS, - [PRODUCTION_ENVIRONMENT]: PRODUCTION_ENVIRONMENT, -}; - -export const dynamicOptionsKeys = [NAME]; - -type Options = { - +customer: number, - +name: string, - +gitUrl: string, - +openshift: number, - +branches: string, - +pullrequests: string, - +productionEnvironment: string, -}; - -export function allOptionsSpecified(options: Options): boolean { - // Return a boolean of whether all possible command options keys... - return R.all( - // ...are contained in keys of the provided object - R.contains(R.__, R.keys(options)), - R.values(commandOptions), - ); -} - -export function builder(yargs: Yargs): Yargs { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [CUSTOMER]: { - describe: 'Customer id to use for new project', - type: 'number', - }, - [NAME]: { - describe: 'Name of new project', - type: 'string', - }, - [GIT_URL]: { - describe: 'Git URL of new project', - type: 'string', - }, - [OPENSHIFT]: { - describe: 'Openshift id to use for new project', - type: 'number', - }, - [BRANCHES]: { - describe: - 'Branches to deploy. Possible values include "false" (no branches), "true" (all branches) and a regular expression to match branches.', - type: 'string', - }, - [PULLREQUESTS]: { - describe: - 'Pull requests to deploy. Possible values include "false" (no pull requests), "true" (all pull requests) and a regular expression to match pull request titles.', - type: 'boolean', - }, - [PRODUCTION_ENVIRONMENT]: { - describe: 'Production environment for new project', - type: 'string', - }, - }) - .example( - `$0 ${command}`, - 'Create new project (will prompt for all input values)\n', - ) - .example( - `$0 ${command} --${NAME} my_project`, - 'Create a new project with the name "my_project" (will prompt for all other values).', - ) - .example( - `$0 ${command} --${GIT_URL} git@github.com:amazeeio/drupal-example.git --${BRANCHES} '(staging|production)' --${PULLREQUESTS} '(Feature:|Hotfix:)`, - 'Create a new project with the Git URL "git@github.com:amazeeio/drupal-example.git" which will have the "staging" and "production" branches and all pull requests with "Feature:" or "Hotfix:" in the title deployed (will prompt for all other values).', - ) - .example( - `$0 ${command} --${CUSTOMER} 1 --${NAME} my_project --${GIT_URL} git@github.com:amazeeio/drupal-example.git --${OPENSHIFT} kickstart-openshift --${BRANCHES} '(staging|production)' --${PULLREQUESTS} '(Feature:|Hotfix:)' --${PRODUCTION_ENVIRONMENT} 'production'`, - 'Create a new project with all options specified (will not prompt the user).', - ); -} - -type Customer = { - value: number, - name: string, -}; - -type Openshift = { - value: number, - name: string, -}; - -export async function getAllowedCustomersAndOpenshifts( - cerr: typeof console.error, -): Promise<{ - allCustomers: ?Array, - allOpenshifts: ?Array, - errors: ?Array, -}> { - const customersAndOpenshiftsResults = await queryGraphQL({ - query: gql` - query AllCustomersAndOpenshiftsForProjectCreate { - allCustomers { - value: id - name - } - allOpenshifts { - value: id - name - } - } - `, - cerr, - }); - - return { - allCustomers: R.path( - ['data', 'allCustomers'], - customersAndOpenshiftsResults, - ), - allOpenshifts: R.path( - ['data', 'allOpenshifts'], - customersAndOpenshiftsResults, - ), - errors: R.prop('errors', customersAndOpenshiftsResults), - }; -} - -// Prompt the user to input data to be used for project creation -export async function promptForProjectInput( - allCustomers: Array, - allOpenshifts: Array, - clog: typeof console.log, - options: Object, -): Promise { - const questions: Array = [ - { - type: 'autocomplete', - name: CUSTOMER, - message: 'Customer:', - source: async (answers, input) => - R.filter( - customer => fuzzysearch(input || '', R.prop('name', customer)), - allCustomers, - ), - // Using the `when` method of the question object, decide where to get the customer based on conditions - // https://github.com/SBoudrias/Inquirer.js/issues/517#issuecomment-288964496 - when(answers) { - return R.cond([ - // 1. If the `customer` is set in the command line arguments or the config, use that customer - answerWithOptionIfSet({ - option: CUSTOMER, - answers, - notify: true, - clog, - }), - // 2. If only one customer was returned from the allCustomers query, use that customer as the answer to the question and tell the user, not prompting them to choose. - [ - R.compose( - R.equals(1), - R.length, - R.prop('allCustomers'), - ), - (customersAndOptions) => { - const firstCustomer = R.compose( - R.head, - R.prop('allCustomers'), - )(customersAndOptions); - clog( - `${blue('!')} Using single authorized customer "${R.prop( - 'name', - firstCustomer, - )}"`, - ); - // $FlowFixMe Covariant property cannot be assigned - answers.customer = R.prop('value', firstCustomer); - return false; - }, - ], - // 3. If more than one customer was returned from the allCustomers query, return true to prompt the user to choose from a list - [R.T, R.T], - ])({ allCustomers, options }); - }, - }, - { - type: 'input', - name: NAME, - message: 'Project name:', - validate: (input: string) => - Boolean(input) || 'Please enter a project name.', - when: answerWithOptionIfSetOrPrompt({ - option: NAME, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: GIT_URL, - message: 'Git URL:', - validate: (input: string) => - // Verify that it is a valid hosted git url... - hostedGitInfoFromUrl(input) !== undefined || - // ...or some other non-hosted formats https://stackoverflow.com/a/22312124/1268612 - /((git|ssh|http(s)?)|(.+@[\w.]+))(:(\/\/)?)([\w.@:/\-~]+)(\.git)(\/)?/.test( - input, - ) || - // If the input is invalid, prompt the user to enter a valid Git URL - 'Please enter a valid Git URL.', - when: answerWithOptionIfSetOrPrompt({ - option: GIT_URL, - options, - notify: true, - clog, - }), - }, - { - type: 'autocomplete', - name: OPENSHIFT, - message: 'Openshift:', - source: async (answers, input) => - R.filter( - openshift => fuzzysearch(input || '', R.prop('name', openshift)), - allOpenshifts, - ), - // Using the `when` method of the question object, decide where to get the openshift based on conditions - // https://github.com/SBoudrias/Inquirer.js/issues/517#issuecomment-288964496 - when(answers) { - return R.cond([ - // 1. If the `openshift` is set in the command line arguments or the config, use that openshift - answerWithOptionIfSet({ - option: OPENSHIFT, - answers, - notify: true, - clog, - }), - // 2. If only one openshift was returned from the allOpenshifts query, use that openshift as the answer to the question and tell the user, not prompting them to choose. - [ - R.compose( - R.equals(1), - R.length, - R.prop('allOpenshifts'), - ), - (openshiftsAndOptions) => { - const firstOpenshift = R.compose( - R.head, - R.prop('allOpenshifts'), - )(openshiftsAndOptions); - clog( - `${blue('!')} Using single authorized openshift "${R.prop( - 'name', - firstOpenshift, - )}"`, - ); - // $FlowFixMe Covariant property cannot be assigned - answers.openshift = R.prop('value', firstOpenshift); - return false; - }, - ], - // 3. If more than one openshift was returned from the allOpenshifts query, return true to prompt the user to choose from a list - [R.T, R.T], - ])({ allOpenshifts, options }); - }, - }, - { - type: 'input', - name: BRANCHES, - message: 'Deploy branches:', - default: 'true', - when: answerWithOptionIfSetOrPrompt({ - option: BRANCHES, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: PULLREQUESTS, - message: 'Pull requests:', - default: null, - when: answerWithOptionIfSetOrPrompt({ - option: PULLREQUESTS, - options, - notify: true, - clog, - }), - }, - { - type: 'input', - name: PRODUCTION_ENVIRONMENT, - message: 'Production environment:', - default: null, - when: answerWithOptionIfSetOrPrompt({ - option: PRODUCTION_ENVIRONMENT, - options, - notify: true, - clog, - }), - }, - ]; - - return inquirer.prompt(questions); -} - -type Args = CommandHandlerArgsWithOptions<{ - +customer?: number, - +name?: string, - +gitUrl?: string, - +openshift?: number, - +branches?: string, - +pullrequests?: string, - +productionEnvironment?: string, -}>; - -type Question = inquirer$Question & { - name: $Values, -}; - -export async function handler({ clog, cerr, options }: Args): Promise { - const { - allCustomers, - allOpenshifts, - errors, - } = await getAllowedCustomersAndOpenshifts(cerr); - - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - if (!allCustomers || R.equals(R.length(allCustomers), 0)) { - return printErrors(cerr, 'No authorized customers found!'); - } - - if (!allOpenshifts || R.equals(R.length(allOpenshifts), 0)) { - return printErrors(cerr, 'No authorized openshifts found!'); - } - - const projectInput = await promptForProjectInput( - allCustomers, - allOpenshifts, - clog, - options, - ); - - const addProjectResult = await queryGraphQL({ - query: gql` - mutation AddProject($input: AddProjectInput!) { - addProject(input: $input) { - id - name - customer { - name - } - gitUrl - activeSystemsDeploy - activeSystemsRemove - branches - pullrequests - openshift { - name - } - created - } - } - `, - cerr, - variables: { - input: projectInput, - }, - }); - - const { errors: addProjectErrors } = addProjectResult; - - if (addProjectErrors != null) { - if ( - /Duplicate entry '[^']+' for key 'name'/.test( - R.prop('message', R.head(addProjectErrors)), - ) - ) { - return printErrors(cerr, { - message: `Project name "${R.prop( - 'name', - projectInput, - )}" already exists! Please select a different project name.`, - }); - } - - return printGraphQLErrors(cerr, ...addProjectErrors); - } - - const project = R.path(['data', 'addProject'], addProjectResult); - - const projectName = R.prop('name', project); - - clog(green(`Project "${projectName}" created successfully:`)); - - clog( - format([ - [ - 'Name', - 'Customer', - 'Git URL', - 'Active Systems Deploy', - 'Active Systems Remove', - 'Branches', - 'Pull Requests', - 'Openshift', - 'Created', - ], - [ - R.prop('name', project), - R.path(['customer', 'name'], project), - R.prop('gitUrl', project), - R.prop('activeSystemsDeploy', project), - R.prop('activeSystemsRemove', project), - R.prop('branches', project), - R.prop('pullrequests', project), - R.path(['openshift', 'name'], project), - R.path(['created'], project), - ], - ]), - ); - - return 0; -} diff --git a/cli/src/commands/projectCommands/delete.js b/cli/src/commands/projectCommands/delete.js deleted file mode 100644 index d4a977ef7..000000000 --- a/cli/src/commands/projectCommands/delete.js +++ /dev/null @@ -1,114 +0,0 @@ -// @flow - -import { green } from 'chalk'; -import inquirer from 'inquirer'; -import R from 'ramda'; - -import { answerWithOptionIfSetOrPrompt } from '../../cli/answerWithOption'; -import gql from '../../util/gql'; -import { printGraphQLErrors, printErrors } from '../../util/printErrors'; -import { queryGraphQL } from '../../util/queryGraphQL'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgsWithOptions } from '../../types/Command'; - -export const command = 'delete'; -export const description = 'Delete a project'; - -export const PROJECT: 'project' = 'project'; - -export const commandOptions = { - [PROJECT]: PROJECT, -}; - -export const dynamicOptionsKeys = [PROJECT]; - -type OptionalOptions = { - project?: string, -}; - -type Options = { - +project: string, -}; - -export function builder(yargs: Yargs): Yargs { - return yargs - .usage(`$0 ${command} - ${description}`) - .options({ - [PROJECT]: { - demandOption: false, - describe: 'Name of project', - type: 'string', - }, - }) - .example(`$0 ${command}`, 'Delete a project (will prompt for project name)') - .example( - `$0 ${command} --${PROJECT} myproject`, - 'Delete the project named "myproject"', - ); -} - -type PromptForQueryOptionsArgs = {| - options: OptionalOptions, - clog: typeof console.log, -|}; - -async function promptForQueryOptions({ - options, - clog, -}: -PromptForQueryOptionsArgs): Promise { - return inquirer.prompt([ - { - type: 'input', - name: PROJECT, - message: 'Project name:', - when: answerWithOptionIfSetOrPrompt({ option: PROJECT, options, clog }), - validate: input => - Boolean(input) || - 'Please enter a project name to delete or press CTRL-C to exit.', - }, - ]); -} - -type Args = CommandHandlerArgsWithOptions<{ - +project?: string, -}>; - -export async function handler({ clog, cerr, options }: Args): Promise { - const { project: projectName } = await promptForQueryOptions({ - options, - clog, - }); - - const result = await queryGraphQL({ - cerr, - query: gql` - mutation DeleteProject($input: DeleteProjectInput!) { - deleteProject(input: $input) - } - `, - variables: { - input: { - project: projectName, - }, - }, - }); - - const { errors } = result; - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - const response = R.path(['data', 'deleteProject'])(result); - - if (!R.equals(response, 'success')) { - return printErrors(cerr, { - message: `Error: API responded with "${response || ''}"`, - }); - } - - clog(green(`Project "${projectName}" deleted successfully!`)); - - return 0; -} diff --git a/cli/src/commands/projects.js b/cli/src/commands/projects.js deleted file mode 100644 index a3774ac96..000000000 --- a/cli/src/commands/projects.js +++ /dev/null @@ -1,83 +0,0 @@ -// @flow - -import R from 'ramda'; - -import format from '../util/format'; -import gql from '../util/gql'; -import { queryGraphQL } from '../util/queryGraphQL'; -import { printGraphQLErrors } from '../util/printErrors'; - -import typeof Yargs from 'yargs'; -import type { CommandHandlerArgs } from '../types/Command'; - -export const command = 'projects'; -export const description = 'List all projects'; - -export function builder(yargs: Yargs) { - return yargs - .usage(`$0 ${command} - ${description}`) - .example(`$0 ${command}`, 'List all projects'); -} - -export async function handler({ - clog, - cerr, -}: -CommandHandlerArgs): Promise { - const query = gql` - query AllProjects { - allProjects { - name - gitUrl - branches - pullrequests - created - } - } - `; - - const result = await queryGraphQL({ - cerr, - query, - }); - - const { errors } = result; - if (errors != null) { - return printGraphQLErrors(cerr, ...errors); - } - - const sortByName = R.sortBy( - R.compose( - R.toLower, - R.propOr('', 'name'), - ), - ); - - const projects = R.compose( - sortByName, - R.pathOr([], ['data', 'allProjects']), - )(result); - - if (projects.length === 0) { - clog('No projects found.'); - return 0; - } - - clog( - format([ - ['Project', 'Git URL', 'Branches', 'Pull Requests', 'Created'], - ...R.map( - project => [ - R.prop('name', project), - R.prop('gitUrl', project), - String(R.prop('branches', project)), - String(R.prop('pullrequests', project)), - R.prop('created', project), - ], - projects, - ), - ]), - ); - - return 0; -} diff --git a/cli/src/config/getApiConfig.js b/cli/src/config/getApiConfig.js deleted file mode 100644 index e5e8f236c..000000000 --- a/cli/src/config/getApiConfig.js +++ /dev/null @@ -1,68 +0,0 @@ -// @flow - -import url from 'url'; -import R from 'ramda'; -import { getConfig } from '.'; - -export const getApiConfig: () => { hostname: string, port: number } = (() => { - let allApiConfig; - - return () => { - if (!allApiConfig) { - // Freeze process.env for Flow - const env = Object.freeze({ ...process.env }); - - // Build API URL from environment variables if protocol, host and port exist - const envApiUrl: string | null = R.ifElse( - R.allPass([ - R.prop('API_PROTOCOL'), - R.prop('API_HOST'), - R.prop('API_PORT'), - ]), - R.always( - `${R.prop('API_PROTOCOL', env)}://${R.prop('API_HOST', env)}:${R.prop( - 'API_PORT', - env, - )}`, - ), - R.always(null), - )(env); - - const apiUrl: string = - // API URL from environment variables - envApiUrl || - // API URL from config - R.prop('api', getConfig()) || - // Default API URL - 'https://api.lagoon.amazeeio.cloud'; - - const { protocol, hostname, port } = url.parse(apiUrl); - - if (!hostname) { - throw new Error( - 'API URL configured under the "api" key in .lagoon.yml doesn\'t contain a valid hostname.', - ); - } - - const defaultProtocol = 'https:'; - const protocolPorts = { - 'https:': 443, - 'http:': 80, - }; - - allApiConfig = { - hostname, - port: R.ifElse( - // If port is truthy... - R.identity, - // ...convert string to number... - Number, - // ...else assign the port based on the protocol or the default port - R.always(R.prop(protocol || defaultProtocol, protocolPorts)), - )(port), - }; - } - - return allApiConfig; - }; -})(); diff --git a/cli/src/config/getSshConfig.js b/cli/src/config/getSshConfig.js deleted file mode 100644 index 72a2f6b43..000000000 --- a/cli/src/config/getSshConfig.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow - -import R from 'ramda'; -import { getConfig } from '.'; - -export const getSshConfig = (() => { - let allSshConfig; - - return () => { - if (!allSshConfig) { - // Freeze process.env for Flow - const env = Object.freeze({ ...process.env }); - - // Parse the host and the port from the config string under `ssh` - const [ - configSshHost: string | null, - configSshPort: string | null, - ] = R.compose((sshConfig) => { - if (sshConfig && R.contains(':', sshConfig)) { - const split = R.split(':', sshConfig); - if (R.length(split) === 2) return split; - } - return [null, null]; - })(R.prop('ssh', getConfig())); - - const host: string = - // Host from environment variable - R.prop('SSH_HOST', env) || - // Host from config - configSshHost || - // Default host - 'ssh.lagoon.amazeeio.cloud'; - - const port: number = - // Port from environment variable (needs to be number for .connect()) - Number(R.prop('SSH_HOST', env)) || - // Port from config (needs to be number for .connect()) - Number(configSshPort) || - // Default port - 32222; - - allSshConfig = { - username: 'lagoon', - host, - port, - }; - } - return allSshConfig; - }; -})(); diff --git a/cli/src/config/globalOptions.js b/cli/src/config/globalOptions.js deleted file mode 100644 index 8e9eef547..000000000 --- a/cli/src/config/globalOptions.js +++ /dev/null @@ -1,37 +0,0 @@ -// @flow - -import os from 'os'; -import path from 'path'; -import R from 'ramda'; - -export const FORMAT: 'format' = 'format'; - -export const FORMAT_CHOICE_TABLE: 'table' = 'table'; -export const FORMAT_CHOICE_SIMPLE: 'simple' = 'simple'; -export const FORMAT_CHOICE_JSON: 'json' = 'json'; -export const FORMAT_CHOICE_CSV: 'csv' = 'csv'; - -export const TOKEN: 'token' = 'token'; - -export const globalOptionDefaults = { - [FORMAT]: FORMAT_CHOICE_TABLE, - [TOKEN]: path.join(os.homedir(), '.lagoon-token'), -}; - -export const globalOptions = { - [FORMAT]: { - describe: 'Output format to use', - type: 'string', - choices: [ - FORMAT_CHOICE_TABLE, - FORMAT_CHOICE_SIMPLE, - FORMAT_CHOICE_JSON, - FORMAT_CHOICE_CSV, - ], - default: R.prop(FORMAT, globalOptionDefaults), - }, - [TOKEN]: { - describe: 'The path to the authentication token', - type: 'string', - }, -}; diff --git a/cli/src/config/index.js b/cli/src/config/index.js deleted file mode 100644 index 27281e4a3..000000000 --- a/cli/src/config/index.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow - -import R from 'ramda'; -import { readConfigFile } from '../configFile/readConfigFile'; -import { globalOptionDefaults } from './globalOptions'; - -import type { Argv } from 'yargs'; -import type { Config } from '../types/Config'; - -let argv = {}; - -export const getConfig = (() => { - let config; - - return ({ - // Dynamic options are options that will likely change every time and should only be specified dynamically. - // Example: the --overwrite option is allowed to be passed as a command line option, but not allowed to be saved in and read from the config file - // Example: the --token option is allowed to be passed as a command line option and environment variable, but not allowed to be read from the config file - dynamicOptionsKeys, - }: { - dynamicOptionsKeys?: Array, - } = {}): Config => { - if (!config) { - if (R.isEmpty(argv)) { - throw new Error( - 'getConfig() called before argv initialized (setConfig() not yet called?)', - ); - } - config = Object.freeze({ - // Manually apply defaults instead of using yargs' `default` option in order to allow config file to override global defaults - // An alternative would be to move everything into yargs (global options, command options, config using yargs.config, environment variables using yargs.env), but this doesn't allow us an easy way to filter out values from only some sources later with the dynamicOptionsKeys option./ - // Maybe just add an option to filter the configFile to readConfigFile? - ...globalOptionDefaults, - ...R.omit(dynamicOptionsKeys || [], readConfigFile() || {}), - ...argv, - }); - } - - return config; - }; -})(); - -export function setConfig({ - argv: newArgv, - dynamicOptionsKeys, -}: { - argv: Argv, - dynamicOptionsKeys: Array, -}): Config { - // Omit yargs-specific properties - argv = R.omit(['_', '$0'], newArgv); - return getConfig({ dynamicOptionsKeys }); -} diff --git a/cli/src/configFile/__tests__/__snapshots__/writeConfigFile.test.js.snap b/cli/src/configFile/__tests__/__snapshots__/writeConfigFile.test.js.snap deleted file mode 100644 index 7c16792a9..000000000 --- a/cli/src/configFile/__tests__/__snapshots__/writeConfigFile.test.js.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`writeConfigFile should convert camelcase keys to snake case before writing config 1`] = ` -"project: your_project -arbitrary_config_key: asdf -" -`; - -exports[`writeConfigFile should write default config to given path 1`] = ` -"project: your_project -" -`; diff --git a/cli/src/configFile/__tests__/lagoon.yml b/cli/src/configFile/__tests__/lagoon.yml deleted file mode 100644 index 7f41ad0ad..000000000 --- a/cli/src/configFile/__tests__/lagoon.yml +++ /dev/null @@ -1 +0,0 @@ -project: amazee_io \ No newline at end of file diff --git a/cli/src/configFile/__tests__/parseConfigFile.test.js b/cli/src/configFile/__tests__/parseConfigFile.test.js deleted file mode 100644 index 6ea9decea..000000000 --- a/cli/src/configFile/__tests__/parseConfigFile.test.js +++ /dev/null @@ -1,23 +0,0 @@ -// @flow - -import path from 'path'; -import { parseConfigFile } from '../parseConfigFile'; - -const fs = require('../../util/fs'); - -// $FlowFixMe Jest can mutate exports https://github.com/facebook/jest/issues/936#issuecomment-214556122 -fs.writeFile = jest.fn(); - -describe('parseConfig', () => { - it('should parse the config correctly', async () => { - const yamlContent = await fs.readFile(path.join(__dirname, 'lagoon.yml')); - - const config = parseConfigFile(yamlContent.toString()); - - const expected = { - project: 'amazee_io', - }; - - expect(config).toEqual(expected); - }); -}); diff --git a/cli/src/configFile/__tests__/writeConfigFile.test.js b/cli/src/configFile/__tests__/writeConfigFile.test.js deleted file mode 100644 index 7dffe4d65..000000000 --- a/cli/src/configFile/__tests__/writeConfigFile.test.js +++ /dev/null @@ -1,49 +0,0 @@ -// @flow - -import { configFileInputOptionsTypes } from '../../types/ConfigFile'; -import { writeConfigFile } from '../writeConfigFile'; - -jest.mock('../../util/fs'); -const fs = require('../../util/fs'); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; -const writeFileMock = _castMockForFlow(fs.writeFile); - -describe('writeConfigFile', () => { - afterEach(() => { - writeFileMock.mockClear(); - }); - - it('should write default config to given path', async () => { - writeConfigFile('lagoon.yml', { - project: 'your_project', - api: '', - ssh: '', - token: '', - }); - const [filename, data] = writeFileMock.mock.calls[0]; - - expect(filename).toBe('lagoon.yml'); - expect(data).toMatchSnapshot(); - }); - - it('should convert camelcase keys to snake case before writing config', async () => { - // $FlowFixMe Jest can mutate exports https://stackoverflow.com/a/42979724/1268612 - configFileInputOptionsTypes.arbitraryConfigKey = String; - - // $FlowFixMe This test uses an invalid arbitrary key here on purpose - writeConfigFile('lagoon.yml', { - project: 'your_project', - arbitraryConfigKey: 'asdf', - api: '', - ssh: '', - token: '', - }); - const [filename, data] = writeFileMock.mock.calls[0]; - - expect(filename).toBe('lagoon.yml'); - expect(data).toMatchSnapshot(); - }); -}); diff --git a/cli/src/configFile/parseConfigFile.js b/cli/src/configFile/parseConfigFile.js deleted file mode 100644 index 778bd2275..000000000 --- a/cli/src/configFile/parseConfigFile.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow - -import camelcaseKeys from 'camelcase-keys'; -import R from 'ramda'; -import yaml from 'js-yaml'; - -import type { ConfigFile } from '../types/ConfigFile'; - -export function parseConfigFile(yamlContent: string): ConfigFile { - // TODO: Add schema validation in here if necessary - return R.compose( - camelcaseKeys, - yaml.safeLoad, - )(yamlContent); -} diff --git a/cli/src/configFile/readConfigFile.js b/cli/src/configFile/readConfigFile.js deleted file mode 100644 index 3b9ed97d0..000000000 --- a/cli/src/configFile/readConfigFile.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow - -import fs from 'fs'; -import findup from 'findup-sync'; -import { parseConfigFile } from './parseConfigFile'; - -import type { ConfigFile } from '../types/ConfigFile'; - -/** - * Find and read the .lagoon.yml config file - */ -export function readConfigFile(): ConfigFile | null { - const configPath = findup('.lagoon.yml'); - - if (configPath == null) { - return null; - } - - const yamlContent = fs.readFileSync(configPath); - return parseConfigFile(yamlContent.toString()); -} diff --git a/cli/src/configFile/writeConfigFile.js b/cli/src/configFile/writeConfigFile.js deleted file mode 100644 index f0ed06581..000000000 --- a/cli/src/configFile/writeConfigFile.js +++ /dev/null @@ -1,53 +0,0 @@ -// @flow - -import yaml from 'js-yaml'; -import R from 'ramda'; -import toSnakeCase from 'to-snake-case'; -import { writeFile } from '../util/fs'; - -import { configFileInputOptionsTypes } from '../types/ConfigFile'; -import type { ConfigFileInput } from '../types/ConfigFile'; - -export function writeConfigFile( - filepath: string, - inputOptions: ConfigFileInput, -): Promise { - const errors = []; - - const snakeCaseInputOptionsWithoutEmptyStrings = R.reduce( - (acc, [optionKey, optionVal]) => { - // Validate - const optionType = R.prop(optionKey, configFileInputOptionsTypes); - - if (!optionType) { - errors.push( - `- Invalid config option "${optionKey}". Valid options: ${R.join( - ', ', - R.keys(configFileInputOptionsTypes), - )}`, - ); - } else if (!R.is(optionType, optionVal)) { - errors.push( - `- Invalid config option value for "${optionKey}": "${optionVal}" expected type: ${R.prop( - 'name', - optionType, - )}`, - ); - } - - // Filter out empty strings - if (!R.both(R.is(String), R.isEmpty)(optionVal)) { - acc[toSnakeCase(optionKey)] = optionVal; - } - - return acc; - }, - {}, - R.toPairs(inputOptions), - ); - - if (R.length(errors) > 0) throw new Error(errors.join('\n')); - - const yamlConfig = yaml.safeDump(snakeCaseInputOptionsWithoutEmptyStrings); - return writeFile(filepath, yamlConfig); -} diff --git a/cli/src/formatters/__tests__/__snapshots__/csv.test.js.snap b/cli/src/formatters/__tests__/__snapshots__/csv.test.js.snap deleted file mode 100644 index 67e6b2de6..000000000 --- a/cli/src/formatters/__tests__/__snapshots__/csv.test.js.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`csv formatter should format data with > 1 data rows correctly 1`] = ` -"Name,Customer -test-project-csv-1,test-customer-csv-1 -test-project-csv-2,test-customer-csv-2 -" -`; - -exports[`csv formatter should format data with 0 data rows correctly 1`] = ` -"Name,Customer -" -`; - -exports[`csv formatter should format data with 1 data row correctly 1`] = ` -"Name,Customer -test-project-csv-1,test-customer-csv-1 -" -`; diff --git a/cli/src/formatters/__tests__/__snapshots__/json.test.js.snap b/cli/src/formatters/__tests__/__snapshots__/json.test.js.snap deleted file mode 100644 index 654c1050d..000000000 --- a/cli/src/formatters/__tests__/__snapshots__/json.test.js.snap +++ /dev/null @@ -1,40 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`json formatter should format data with > 1 data rows correctly 1`] = ` -Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-json-1", - "test-customer-json-1", - ], - Array [ - "test-project-json-2", - "test-customer-json-2", - ], -] -`; - -exports[`json formatter should format data with 0 data rows correctly 1`] = ` -Array [ - Array [ - "Name", - "Customer", - ], -] -`; - -exports[`json formatter should format data with 1 data row correctly 1`] = ` -Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-json-1", - "test-customer-json-1", - ], -] -`; diff --git a/cli/src/formatters/__tests__/__snapshots__/simple.test.js.snap b/cli/src/formatters/__tests__/__snapshots__/simple.test.js.snap deleted file mode 100644 index abe84c5e8..000000000 --- a/cli/src/formatters/__tests__/__snapshots__/simple.test.js.snap +++ /dev/null @@ -1,16 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`simple formatter should format data with > 1 data rows correctly 1`] = ` -"Name: test-project-simple-1 -Customer: test-customer-simple-1 - -Name: test-project-simple-2 -Customer: test-customer-simple-2" -`; - -exports[`simple formatter should format data with 0 data rows correctly 1`] = `""`; - -exports[`simple formatter should format data with 1 data row correctly 1`] = ` -"Name: test-project-simple-1 -Customer: test-customer-simple-1" -`; diff --git a/cli/src/formatters/__tests__/__snapshots__/table.test.js.snap b/cli/src/formatters/__tests__/__snapshots__/table.test.js.snap deleted file mode 100644 index 4c1d21c04..000000000 --- a/cli/src/formatters/__tests__/__snapshots__/table.test.js.snap +++ /dev/null @@ -1,14 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`table formatter should format data with > 1 data rows correctly 1`] = ` -"Name Customer -test-project-table-1 test-customer-table-1 -test-project-table-2 test-customer-table-2" -`; - -exports[`table formatter should format data with 0 data rows correctly 1`] = `"Name Customer"`; - -exports[`table formatter should format data with 1 data row correctly 1`] = ` -"Name test-project-table-1 -Customer test-customer-table-1" -`; diff --git a/cli/src/formatters/__tests__/csv.test.js b/cli/src/formatters/__tests__/csv.test.js deleted file mode 100644 index cd7e0b863..000000000 --- a/cli/src/formatters/__tests__/csv.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// @flow - -import formatAsCsv from '../csv'; - -describe('csv formatter', () => { - it('should format data with 0 data rows correctly', () => { - const formatted = formatAsCsv([['Name', 'Customer']]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with 1 data row correctly', () => { - const formatted = formatAsCsv([ - ['Name', 'Customer'], - ['test-project-csv-1', 'test-customer-csv-1'], - ]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with > 1 data rows correctly', () => { - const formatted = formatAsCsv([ - ['Name', 'Customer'], - ['test-project-csv-1', 'test-customer-csv-1'], - ['test-project-csv-2', 'test-customer-csv-2'], - ]); - expect(formatted).toMatchSnapshot(); - }); -}); diff --git a/cli/src/formatters/__tests__/json.test.js b/cli/src/formatters/__tests__/json.test.js deleted file mode 100644 index 787563379..000000000 --- a/cli/src/formatters/__tests__/json.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// @flow - -import formatAsJson from '../json'; - -describe('json formatter', () => { - it('should format data with 0 data rows correctly', () => { - const formatted = formatAsJson([['Name', 'Customer']]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with 1 data row correctly', () => { - const formatted = formatAsJson([ - ['Name', 'Customer'], - ['test-project-json-1', 'test-customer-json-1'], - ]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with > 1 data rows correctly', () => { - const formatted = formatAsJson([ - ['Name', 'Customer'], - ['test-project-json-1', 'test-customer-json-1'], - ['test-project-json-2', 'test-customer-json-2'], - ]); - expect(formatted).toMatchSnapshot(); - }); -}); diff --git a/cli/src/formatters/__tests__/simple.test.js b/cli/src/formatters/__tests__/simple.test.js deleted file mode 100644 index 4a6bcb3cb..000000000 --- a/cli/src/formatters/__tests__/simple.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// @flow - -import formatAsSimple from '../simple'; - -describe('simple formatter', () => { - it('should format data with 0 data rows correctly', () => { - const formatted = formatAsSimple([['Name', 'Customer']]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with 1 data row correctly', () => { - const formatted = formatAsSimple([ - ['Name', 'Customer'], - ['test-project-simple-1', 'test-customer-simple-1'], - ]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with > 1 data rows correctly', () => { - const formatted = formatAsSimple([ - ['Name', 'Customer'], - ['test-project-simple-1', 'test-customer-simple-1'], - ['test-project-simple-2', 'test-customer-simple-2'], - ]); - expect(formatted).toMatchSnapshot(); - }); -}); diff --git a/cli/src/formatters/__tests__/table.test.js b/cli/src/formatters/__tests__/table.test.js deleted file mode 100644 index 697475325..000000000 --- a/cli/src/formatters/__tests__/table.test.js +++ /dev/null @@ -1,27 +0,0 @@ -// @flow - -import formatAsTable from '../table'; - -describe('table formatter', () => { - it('should format data with 0 data rows correctly', () => { - const formatted = formatAsTable([['Name', 'Customer']]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with 1 data row correctly', () => { - const formatted = formatAsTable([ - ['Name', 'Customer'], - ['test-project-table-1', 'test-customer-table-1'], - ]); - expect(formatted).toMatchSnapshot(); - }); - - it('should format data with > 1 data rows correctly', () => { - const formatted = formatAsTable([ - ['Name', 'Customer'], - ['test-project-table-1', 'test-customer-table-1'], - ['test-project-table-2', 'test-customer-table-2'], - ]); - expect(formatted).toMatchSnapshot(); - }); -}); diff --git a/cli/src/formatters/csv.js b/cli/src/formatters/csv.js deleted file mode 100644 index 5df390c30..000000000 --- a/cli/src/formatters/csv.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export { default } from 'csv-stringify/lib/sync'; diff --git a/cli/src/formatters/json.js b/cli/src/formatters/json.js deleted file mode 100644 index faf796643..000000000 --- a/cli/src/formatters/json.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export { identity as default } from 'ramda'; diff --git a/cli/src/formatters/simple.js b/cli/src/formatters/simple.js deleted file mode 100644 index 073e2ad8f..000000000 --- a/cli/src/formatters/simple.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow - -import R from 'ramda'; -import type { FormatData } from '../types/Format'; - -export default function formatAsSimple(data: FormatData) { - const columnHeadings = R.head(data); - return R.compose( - R.join('\n\n'), - R.map( - R.compose( - R.join('\n'), - (R.addIndex(R.map): Function)( - (val, key) => `${R.nth(key, columnHeadings)}: ${val}`, - ), - ), - ), - R.slice(1, Infinity), - )(data); -} diff --git a/cli/src/formatters/table.js b/cli/src/formatters/table.js deleted file mode 100644 index 53bc9e70b..000000000 --- a/cli/src/formatters/table.js +++ /dev/null @@ -1,56 +0,0 @@ -// @flow - -import chalk from 'chalk'; -import R from 'ramda'; -import stripAnsi from 'strip-ansi'; -import table from 'text-table'; -import type { FormatData } from '../types/Format'; - -// Cast all non-string values to strings in a 2-level nested array -const castNonStringsToStrings = R.map( - R.map( - R.ifElse( - // If the value is a string... - R.is(String), - // ...just return the value... - R.identity, - // ...otherwise cast it. - String, - ), - ), -); - -const colorHeadings = R.over( - // Modify the heading row... - R.lensIndex(0), - // ...to be a middle gray color - R.map(chalk.hex('#848484')), -); - -const showSingleDataRowHeadingsOnLeft = R.ifElse( - // If the length of the data is exactly 2 (one data row + one heading row)... - R.compose( - R.equals(2), - R.length, - ), - // ...display the data with the headings on the left instead of on the top... - R.transpose, - // ...otherwise don't transform anything. - R.identity, -); - -export default function formatAsTable(data: FormatData) { - return table( - R.compose( - showSingleDataRowHeadingsOnLeft, - colorHeadings, - castNonStringsToStrings, - )(data), - { - // Calculate string length correctly for the columns - stringLength(str) { - return stripAnsi(str).length; - }, - }, - ); -} diff --git a/cli/src/index.js b/cli/src/index.js deleted file mode 100644 index eacbb4740..000000000 --- a/cli/src/index.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export { registerCommands as run } from './cli/registerCommands'; diff --git a/cli/src/types/Command.js b/cli/src/types/Command.js deleted file mode 100644 index d4cfabcd4..000000000 --- a/cli/src/types/Command.js +++ /dev/null @@ -1,18 +0,0 @@ -// @flow - -import type { Config } from './Config'; - -export type CommandHandlerArgs = { - options: Config, - cwd: string, - clog: typeof console.log, - cerr: typeof console.error, -}; - -export type CommandHandlerArgsWithOptions = { - ...$Exact, - options: {| - ...$Exact<$PropertyType>, - ...$Exact, - |}, -}; diff --git a/cli/src/types/Config.js b/cli/src/types/Config.js deleted file mode 100644 index e10d89002..000000000 --- a/cli/src/types/Config.js +++ /dev/null @@ -1,10 +0,0 @@ -// @flow - -import type { ConfigFile } from './ConfigFile'; - -export type Config = { - ...ConfigFile, - // Global config options - format: string, - token: string, -}; diff --git a/cli/src/types/ConfigFile.js b/cli/src/types/ConfigFile.js deleted file mode 100644 index 6e430328c..000000000 --- a/cli/src/types/ConfigFile.js +++ /dev/null @@ -1,32 +0,0 @@ -// @flow - -// TODO: Type the rest of the config file - -// Snake case properties are used here with the yaml config file -// to be more consistent with other config files -export type ConfigFile = { - +api?: string, - +branches?: string, - +customer?: number, - +git_url?: string, - +openshift?: number, - +production_environment?: string, - +project?: string, - +pullrequests?: string, - +ssh?: string, - +token?: string, -}; - -export type ConfigFileInput = {| - project: string, - api: string, - ssh: string, - token: string, -|}; - -export const configFileInputOptionsTypes = { - project: String, - api: String, - ssh: String, - token: String, -}; diff --git a/cli/src/types/Format.js b/cli/src/types/Format.js deleted file mode 100644 index 5090f8c50..000000000 --- a/cli/src/types/Format.js +++ /dev/null @@ -1,3 +0,0 @@ -// @flow - -export type FormatData = Array>; diff --git a/cli/src/util/__tests__/__snapshots__/format.test.js.snap b/cli/src/util/__tests__/__snapshots__/format.test.js.snap deleted file mode 100644 index fd10d798b..000000000 --- a/cli/src/util/__tests__/__snapshots__/format.test.js.snap +++ /dev/null @@ -1,69 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`format should call csv formatter with correct configuration 1`] = ` -Array [ - Array [ - Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-csv", - "test-customer-csv", - ], - ], - ], -] -`; - -exports[`format should call json formatter with correct configuration 1`] = ` -Array [ - Array [ - Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-json", - "test-customer-json", - ], - ], - ], -] -`; - -exports[`format should call simple formatter with correct configuration 1`] = ` -Array [ - Array [ - Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-simple", - "test-customer-simple", - ], - ], - ], -] -`; - -exports[`format should call table formatter with correct configuration 1`] = ` -Array [ - Array [ - Array [ - Array [ - "Name", - "Customer", - ], - Array [ - "test-project-table", - "test-customer-table", - ], - ], - ], -] -`; diff --git a/cli/src/util/__tests__/__snapshots__/printErrors.test.js.snap b/cli/src/util/__tests__/__snapshots__/printErrors.test.js.snap deleted file mode 100644 index 708d98b06..000000000 --- a/cli/src/util/__tests__/__snapshots__/printErrors.test.js.snap +++ /dev/null @@ -1,61 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`printErrors should print objects with a message key 1`] = ` -Array [ - Array [ - "arbitraryValue", - ], -] -`; - -exports[`printGraphQLErrors should print multiple GraphQLErrors 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned errors:", - ], - Array [ - "A GraphQLError message", - ], - Array [ - "Another GraphQLError message", - ], -] -`; - -exports[`printGraphQLErrors should print singular GraphQLErrors 1`] = ` -Array [ - Array [ - "Oops! The Lagoon API returned an error:", - ], - Array [ - "A GraphQLError message", - ], -] -`; - -exports[`printGraphQLErrors should tell the user to log in if there is a bearer token error 1`] = ` -Array [ - Array [ - "No authentication token found. Please log in first with \\"lagoon login\\". -Online documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-login", - ], -] -`; - -exports[`printNoConfigError should print an error about the configuration file not being found 1`] = ` -Array [ - Array [ - ".lagoon.yml config file not found. Please create one with \\"lagoon init\\". -Online documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-init", - ], -] -`; - -exports[`printProjectConfigurationError should print an error about missing project configuration 1`] = ` -Array [ - Array [ - "No project configured. Please create a .lagoon.yml config file with \\"lagoon init\\" or pass a project to this command via the --project option. -Online documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-init", - ], -] -`; diff --git a/cli/src/util/__tests__/__snapshots__/runSshCommand.test.js.snap b/cli/src/util/__tests__/__snapshots__/runSshCommand.test.js.snap deleted file mode 100644 index a3fd58e56..000000000 --- a/cli/src/util/__tests__/__snapshots__/runSshCommand.test.js.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`runSshCommand should call execa with correct arguments and return stdout 1`] = ` -Array [ - Array [ - "ssh", - Array [ - "-p", - "2020", - "-i", - "./identity/path", - "-F", - "/dev/null", - "-o", - "AddKeysToAgent=no", - "-o", - "IdentitiesOnly=yes", - "lagoon@localhost", - "token", - ], - ], -] -`; diff --git a/cli/src/util/__tests__/format.test.js b/cli/src/util/__tests__/format.test.js deleted file mode 100644 index 5781a4d16..000000000 --- a/cli/src/util/__tests__/format.test.js +++ /dev/null @@ -1,93 +0,0 @@ -// @flow - -import format from '../format'; -import { getConfig } from '../../config'; -import formatAsTable from '../../formatters/table'; -import formatAsSimple from '../../formatters/simple'; -import formatAsJson from '../../formatters/json'; -import formatAsCsv from '../../formatters/csv'; - -jest.mock('../../config'); -jest.mock('../../formatters/table'); -jest.mock('../../formatters/simple'); -jest.mock('../../formatters/json'); -jest.mock('../../formatters/csv'); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -const formatAsTableMock = _castMockForFlow(formatAsTable); -const formatAsSimpleMock = _castMockForFlow(formatAsSimple); -const formatAsJsonMock = _castMockForFlow(formatAsJson); -const formatAsCsvMock = _castMockForFlow(formatAsCsv); - -describe('format', () => { - afterEach(() => { - formatAsTableMock.mockClear(); - formatAsSimpleMock.mockClear(); - formatAsJsonMock.mockClear(); - formatAsCsvMock.mockClear(); - }); - - it('should call table formatter with correct configuration', () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'table', - })); - format([ - ['Name', 'Customer'], - ['test-project-table', 'test-customer-table'], - ]); - expect(formatAsTableMock.mock.calls).toMatchSnapshot(); - expect(formatAsSimpleMock.mock.calls.length).toBe(0); - expect(formatAsJsonMock.mock.calls.length).toBe(0); - expect(formatAsCsvMock.mock.calls.length).toBe(0); - }); - - it('should call simple formatter with correct configuration', () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'simple', - })); - format([ - ['Name', 'Customer'], - ['test-project-simple', 'test-customer-simple'], - ]); - expect(formatAsSimpleMock.mock.calls).toMatchSnapshot(); - expect(formatAsTableMock.mock.calls.length).toBe(0); - expect(formatAsJsonMock.mock.calls.length).toBe(0); - expect(formatAsCsvMock.mock.calls.length).toBe(0); - }); - - it('should call json formatter with correct configuration', () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'json', - })); - format([['Name', 'Customer'], ['test-project-json', 'test-customer-json']]); - expect(formatAsJsonMock.mock.calls).toMatchSnapshot(); - expect(formatAsTableMock.mock.calls.length).toBe(0); - expect(formatAsSimpleMock.mock.calls.length).toBe(0); - expect(formatAsCsvMock.mock.calls.length).toBe(0); - }); - - it('should call csv formatter with correct configuration', () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'csv', - })); - format([['Name', 'Customer'], ['test-project-csv', 'test-customer-csv']]); - expect(formatAsCsvMock.mock.calls).toMatchSnapshot(); - expect(formatAsTableMock.mock.calls.length).toBe(0); - expect(formatAsSimpleMock.mock.calls.length).toBe(0); - expect(formatAsJsonMock.mock.calls.length).toBe(0); - }); - - it("shouldn't call any formatter with an incorrect configuration", () => { - _castMockForFlow(getConfig).mockImplementationOnce(() => ({ - format: 'non-existent formatting option', - })); - format([['Name', 'Customer'], ['test-project-none', 'test-customer-none']]); - expect(formatAsTableMock.mock.calls.length).toBe(0); - expect(formatAsSimpleMock.mock.calls.length).toBe(0); - expect(formatAsJsonMock.mock.calls.length).toBe(0); - expect(formatAsCsvMock.mock.calls.length).toBe(0); - }); -}); diff --git a/cli/src/util/__tests__/printErrors.test.js b/cli/src/util/__tests__/printErrors.test.js deleted file mode 100644 index 9d8e83282..000000000 --- a/cli/src/util/__tests__/printErrors.test.js +++ /dev/null @@ -1,66 +0,0 @@ -// @flow - -import { - printErrors, - printNoConfigError, - printProjectConfigurationError, - printGraphQLErrors, -} from '../printErrors'; - -describe('printErrors', () => { - it('should print objects with a message key', () => { - const cerr = jest.fn(); - const code = printErrors(cerr, { message: 'arbitraryValue' }); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); - -describe('printNoConfigError', () => { - it('should print an error about the configuration file not being found', () => { - const cerr = jest.fn(); - const code = printNoConfigError(cerr); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); - -describe('printProjectConfigurationError', () => { - it('should print an error about missing project configuration', () => { - const cerr = jest.fn(); - const code = printProjectConfigurationError(cerr); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); - -describe('printGraphQLErrors', () => { - it('should print singular GraphQLErrors', () => { - const cerr = jest.fn(); - const code = printGraphQLErrors(cerr, { - message: 'A GraphQLError message', - }); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should print multiple GraphQLErrors', () => { - const cerr = jest.fn(); - const code = printGraphQLErrors( - cerr, - { message: 'A GraphQLError message' }, - { message: 'Another GraphQLError message' }, - ); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); - - it('should tell the user to log in if there is a bearer token error', () => { - const cerr = jest.fn(); - const code = printGraphQLErrors(cerr, { - message: 'Unauthorized - Bearer Token Required', - }); - expect(code).toBe(1); - expect(cerr.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/cli/src/util/__tests__/queryGraphQL.test.js b/cli/src/util/__tests__/queryGraphQL.test.js deleted file mode 100644 index 64c9b8027..000000000 --- a/cli/src/util/__tests__/queryGraphQL.test.js +++ /dev/null @@ -1,130 +0,0 @@ -// @flow - -import { queryGraphQL } from '../queryGraphQL'; -import request from '../request'; - -import * as allConfigExports from '../../config'; -import * as allApiConfigExports from '../../config/getApiConfig'; - -jest.mock('../request'); - -jest.mock('../fs', () => ({ - fileExists: jest.fn(async () => true), - readFile: jest.fn(async () => 'TOKEN'), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -describe('queryGraphQL', () => { - it('should reject because of missing hostname', async () => { - // $FlowFixMe Jest can mutate exports https://stackoverflow.com/a/42979724/1268612 - allConfigExports.getConfig = () => ({ - api: 'invalid-url', - format: 'table', - }); - - const mockedRequest = _castMockForFlow(request); - - try { - await queryGraphQL({ - cerr: jest.fn(), - query: '', - }); - } catch (err) { - // request should not be called in that case - const call = mockedRequest.mock.calls; - expect(call).toEqual([]); - - expect(err).toEqual( - new Error( - 'API URL configured under the "api" key in .lagoon.yml doesn\'t contain a valid hostname.', - ), - ); - } - - mockedRequest.mockClear(); - }); - - it('should do a POST request via GraphQL', async () => { - // $FlowFixMe Jest can mutate exports https://stackoverflow.com/a/42979724/1268612 - allConfigExports.getConfig = () => ({ - format: 'table', - }); - - const mockedRequest = _castMockForFlow(request).mockImplementationOnce(() => - Promise.resolve({ data: 'data' }), - ); - - const result = await queryGraphQL({ - cerr: jest.fn(), - query: 'test', - }); - - // Check if the url parsing was correct - const call = mockedRequest.mock.calls[0][0]; - - expect(call).toEqual({ - hostname: 'api.lagoon.amazeeio.cloud', - path: '/graphql', - port: 443, - protocol: 'https:', - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - Authorization: 'Bearer TOKEN', - }, - body: '{"query":"test"}', - rejectUnauthorized: false, - }); - - expect(result).toEqual({ data: 'data' }); - - mockedRequest.mockClear(); - }); - - it('should do a POST request to a custom API via GraphQL', async () => { - // $FlowFixMe Jest can mutate exports https://stackoverflow.com/a/42979724/1268612 - allConfigExports.getConfig = () => ({ - format: 'table', - }); - - // $FlowFixMe Jest can mutate exports https://stackoverflow.com/a/42979724/1268612 - allApiConfigExports.getApiConfig = () => ({ - hostname: 'www.example.com', - port: 443, - }); - - const mockedRequest = _castMockForFlow(request).mockImplementationOnce(() => - Promise.resolve({ data: 'data' }), - ); - - const result = await queryGraphQL({ - cerr: jest.fn(), - query: 'test', - }); - - // Check if the url parsing was correct - const call = mockedRequest.mock.calls[0][0]; - - expect(call).toEqual({ - hostname: 'www.example.com', - path: '/graphql', - port: 443, - protocol: 'https:', - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - Authorization: 'Bearer TOKEN', - }, - body: '{"query":"test"}', - rejectUnauthorized: false, - }); - - expect(result).toEqual({ data: 'data' }); - mockedRequest.mockClear(); - }); -}); diff --git a/cli/src/util/__tests__/request.test.js b/cli/src/util/__tests__/request.test.js deleted file mode 100644 index 4de5bdf48..000000000 --- a/cli/src/util/__tests__/request.test.js +++ /dev/null @@ -1,81 +0,0 @@ -// @flow - -import request from '../request'; -import { Readable } from 'stream'; -import { request as httpsReq } from 'https'; - -jest.mock('https'); - -// https.request works with low level streams, this helper will -// mock a response stream -const resStream = (content: string | Object): stream$Readable => { - const res = new Readable(); - let parsed = content; - - if (typeof parsed === 'object') { - parsed = JSON.stringify(parsed, null, 2); - } - - res.push(parsed); - res.push(null); - return res; -}; - -// Same for request streams -const reqStream = () => ({ - write: jest.fn(), - end: jest.fn(), - on: jest.fn(), -}); - -describe('request', () => { - it('should do POST request with body', async () => { - // We want to check some write() calls on that - const req = reqStream(); - - httpsReq.mockImplementationOnce((options, cb) => { - const res = resStream({ data: 'test' }); - cb(res); - - // returns our mocked req object - return req; - }); - - const result = await request({ - hostname: '', - port: 443, - protocol: 'https:', - path: '', - method: 'POST', - headers: { some: 'header' }, - body: 'some body', - }); - - expect(result).toEqual({ data: 'test' }); - }); - - it('should do GET request without body', async () => { - // We want to check some write() calls on that - const req = reqStream(); - - httpsReq.mockImplementationOnce((options, cb) => { - const res = resStream({ data: 'test' }); - cb(res); - - // returns our mocked req object - return req; - }); - - const result = await request({ - hostname: '', - port: 443, - protocol: 'https:', - path: '', - method: 'GET', - headers: { some: 'header' }, - }); - - expect(result).toEqual({ data: 'test' }); - expect(req.write.mock.calls).toEqual([]); - }); -}); diff --git a/cli/src/util/__tests__/runSshCommand.test.js b/cli/src/util/__tests__/runSshCommand.test.js deleted file mode 100644 index aedff7d51..000000000 --- a/cli/src/util/__tests__/runSshCommand.test.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow - -import execa from 'execa'; -import { runSshCommand } from '../runSshCommand'; - -jest.mock('execa'); -jest.mock('../../config/getSshConfig', () => ({ - getSshConfig: () => ({ username: 'lagoon', host: 'localhost', port: 2020 }), -})); - -// Flow does not know which objects are actual mocks -// this function casts given parameter to JestMockFn -const _castMockForFlow = (mockFn: any): JestMockFn => mockFn; - -const mockedExeca = _castMockForFlow(execa); -const stdout = 'mocked stdout content\nsecondline'; - -mockedExeca.mockImplementation(async () => ({ - stdout, -})); - -describe('runSshCommand', () => { - it('should call execa with correct arguments and return stdout', async () => { - const returned = await runSshCommand({ - command: 'token', - identity: './identity/path', - }); - const execaCalls = mockedExeca.mock.calls; - expect(execaCalls.length).toBe(1); - expect(execaCalls).toMatchSnapshot(); - expect(returned).toBe(stdout); - }); - - it('should throw stderr on error', async () => { - const stderrContent = 'mocked stderr content\nanother second line'; - mockedExeca.mockImplementationOnce(async () => { - throw { - stderr: stderrContent, - }; - }); - try { - await runSshCommand({ - command: 'token', - identity: './identity/path', - }); - } catch (err) { - expect(err).toBe(stderrContent); - } - }); -}); diff --git a/cli/src/util/format.js b/cli/src/util/format.js deleted file mode 100644 index f0c4c2554..000000000 --- a/cli/src/util/format.js +++ /dev/null @@ -1,34 +0,0 @@ -// @flow - -import R from 'ramda'; -import { - FORMAT, - FORMAT_CHOICE_TABLE, - FORMAT_CHOICE_SIMPLE, - FORMAT_CHOICE_JSON, - FORMAT_CHOICE_CSV, -} from '../config/globalOptions'; -import { getConfig } from '../config'; - -import type { FormatData } from '../types/Format'; - -export default function format(data: FormatData) { - return R.cond([ - [ - R.equals(FORMAT_CHOICE_TABLE), - () => require('../formatters/table').default(data), - ], - [ - R.equals(FORMAT_CHOICE_SIMPLE), - () => require('../formatters/simple').default(data), - ], - [ - R.equals(FORMAT_CHOICE_JSON), - () => require('../formatters/json').default(data), - ], - [ - R.equals(FORMAT_CHOICE_CSV), - () => require('../formatters/csv').default(data), - ], - ])(R.prop(FORMAT, getConfig())); -} diff --git a/cli/src/util/fs.js b/cli/src/util/fs.js deleted file mode 100644 index 91b3411ac..000000000 --- a/cli/src/util/fs.js +++ /dev/null @@ -1,36 +0,0 @@ -// @flow - -/** - * This module exists to promisify all the fs functionality - */ - -import fs from 'fs'; -import util from 'util'; - -import type { Stats } from 'fs'; - -type ReadFileFn = (filename: string, enc?: string) => Promise; -type WriteFileFn = ( - filename: string, - data: Buffer | string, - options?: Object | string, -) => Promise; -type UnlinkFn = (filename: string) => Promise; - -export const readFile: ReadFileFn = util.promisify(fs.readFile); -export const writeFile: WriteFileFn = util.promisify(fs.writeFile); -export const unlink: UnlinkFn = util.promisify(fs.unlink); - -export async function fileExists(path: string): Promise { - try { - const stats: Stats = await util.promisify(fs.lstat)(path); - - if (stats.isFile()) { - return true; - } - - return false; - } catch (err) { - return false; - } -} diff --git a/cli/src/util/getCommandOptions.js b/cli/src/util/getCommandOptions.js deleted file mode 100644 index 4df020f65..000000000 --- a/cli/src/util/getCommandOptions.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow - -import R from 'ramda'; -import { globalOptions } from '../config/globalOptions'; - -import type { Config } from '../types/Config'; - -export function getCommandOptions({ - config, - commandOptions, -}: {| - config: Config, - commandOptions: CommandOptionsT, -|}): { [key: $Keys]: any, ...$Exact } { - // Only return the properties that match the command options - return R.pick( - R.concat(R.keys(globalOptions), R.keys(commandOptions)), - config, - ); -} diff --git a/cli/src/util/gql.js b/cli/src/util/gql.js deleted file mode 100644 index 13b7be75b..000000000 --- a/cli/src/util/gql.js +++ /dev/null @@ -1,20 +0,0 @@ -// @flow - -// A no-op tagged template function to mark strings as GraphQL for tooling -export default function gql( - literals: Array, - ...substitutions: Array -) { - let result = ''; - - // run the loop only for the substitution count - substitutions.forEach((substitution, key) => { - result += literals[key]; - result += substitution; - }); - - // add the last literal - result += literals[literals.length - 1]; - - return result; -} diff --git a/cli/src/util/printErrors.js b/cli/src/util/printErrors.js deleted file mode 100644 index a4dfbcf9b..000000000 --- a/cli/src/util/printErrors.js +++ /dev/null @@ -1,64 +0,0 @@ -// @flow - -import { red } from 'chalk'; -import R from 'ramda'; - -type Cerr = typeof console.error; -type LaguError = { +message: string, +stack?: string }; - -export function printErrors( - cerr: Cerr, - ...errors: Array -): number { - R.compose( - R.forEach(cerr), - R.map(red), - R.map( - err => - typeof err === 'string' - ? err - : R.propOr( - // ...otherwise, use the message property as a fallback - R.prop('message', err), - // Try to get the stack... - 'stack', - err, - ), - ), - )(errors); - return 1; -} - -export function printNoConfigError(cerr: Cerr): number { - return printErrors(cerr, { - message: - '.lagoon.yml config file not found. Please create one with "lagoon init".\nOnline documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-init', - }); -} - -export function printProjectConfigurationError(cerr: Cerr): number { - return printErrors(cerr, { - message: - 'No project configured. Please create a .lagoon.yml config file with "lagoon init" or pass a project to this command via the --project option.\nOnline documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-init', - }); -} - -export function printGraphQLErrors( - cerr: Cerr, - ...errors: Array -): number { - if ( - R.find(R.propEq('message', 'Unauthorized - Bearer Token Required'))(errors) - ) { - return printErrors(cerr, { - message: - 'No authentication token found. Please log in first with "lagoon login".\nOnline documentation: https://github.com/amazeeio/lagoon/blob/master/cli/README.md#lagoon-login', - }); - } - const errorsPluralized = R.length(errors) === 1 ? 'an error' : 'errors'; - return printErrors( - cerr, - `Oops! The Lagoon API returned ${errorsPluralized}:`, - ...errors, - ); -} diff --git a/cli/src/util/queryGraphQL.js b/cli/src/util/queryGraphQL.js deleted file mode 100644 index 6d10723ec..000000000 --- a/cli/src/util/queryGraphQL.js +++ /dev/null @@ -1,85 +0,0 @@ -// @flow - -import R from 'ramda'; -import { getConfig } from '../config'; -import { getApiConfig } from '../config/getApiConfig'; -import { fileExists, readFile } from './fs'; -import request from './request'; -import { printErrors } from './printErrors'; - -type QLQueryArgs = { - cerr: typeof console.error, - query: string, - variables?: Object, - headers?: Object, - pretty?: boolean, -}; - -export async function queryGraphQL({ - cerr, - query, - variables, - headers: customHeaders = {}, - pretty = false, -}: -QLQueryArgs): Object { - const headers = { - Accept: 'application/json', - 'Content-Type': 'application/json', - ...customHeaders, - }; - - if (!headers.Authorization) { - const tokenFile = R.prop('token', getConfig()); - const tokenFileExists = await fileExists(tokenFile); - - if (tokenFileExists) { - const tokenBuffer = await readFile(tokenFile); - const token = tokenBuffer.toString().replace(/(\r\n|\n|\r)/gm, ''); - headers.Authorization = `Bearer ${token}`; - } - } - - const { hostname, port } = getApiConfig(); - - const protocol = R.equals(port, 443) ? 'https:' : 'http:'; - - const options = { - hostname, - path: '/graphql', - port, - protocol, - method: 'POST', - headers, - body: JSON.stringify( - { - query, - variables, - }, - null, - pretty ? 2 : 0, - ), - rejectUnauthorized: false, - }; - - let response; - - try { - response = await request(options); - } catch (err) { - const error = R.ifElse( - // For socket hang ups... - R.propEq('message', 'socket hang up'), - // ...print a nicer error message... - R.always( - `Could not connect to Lagoon API at ${protocol}//${hostname}:${port}/graphql.`, - ), - // ...otherwise just return the error message - R.prop('message'), - )(err); - printErrors(cerr, error); - process.exit(1); - } - - return response; -} diff --git a/cli/src/util/request.js b/cli/src/util/request.js deleted file mode 100644 index 8b38940d7..000000000 --- a/cli/src/util/request.js +++ /dev/null @@ -1,51 +0,0 @@ -// @flow - -import R from 'ramda'; - -export type RequestOptions = { - hostname: string, - path?: string, - port: number, - protocol: 'http:' | 'https:', - method: 'GET' | 'POST', - headers?: Object, - rejectUnauthorized?: boolean, - body?: string, -}; - -export default function request(options: RequestOptions): Promise { - return new Promise((resolve, reject) => { - const { body, protocol } = options; - - const protocolModule = R.equals(protocol, 'https:') - ? require('https') - : require('http'); - - const req = protocolModule.request(options, (res) => { - res.setEncoding('utf8'); - - let rawData = ''; - - res.on('data', (chunk) => { - rawData += chunk; - }); - - res.on('end', () => { - try { - const parsed = JSON.parse(rawData); - resolve(parsed); - } catch (e) { - reject(e); - } - }); - }); - - if (body) { - req.write(body); - } - - req.end(); - - req.on('error', e => reject(e)); - }); -} diff --git a/cli/src/util/runSshCommand.js b/cli/src/util/runSshCommand.js deleted file mode 100644 index b01280314..000000000 --- a/cli/src/util/runSshCommand.js +++ /dev/null @@ -1,43 +0,0 @@ -// @flow - -import execa from 'execa'; -import R from 'ramda'; -import { getSshConfig } from '../config/getSshConfig'; - -export async function runSshCommand({ - command, - identity, -}: { - command: string, - identity: string, -}): Promise { - const { username, host, port } = getSshConfig(); - - // TODO: Consider reading the password and passing it along to the `ssh` command using something like node-pty (needed because ssh reads directly from tty https://github.com/nodejs/node-v0.x-archive/issues/1157#issuecomment-7339123). This would allow you to maintain a more consistent design + user experience. - let output = {}; - - try { - output = await execa('ssh', [ - '-p', - String(port), - '-i', - identity, - // Ignore any ssh configuration changed by the user - // https://man.openbsd.org/ssh#F - '-F', - '/dev/null', - // Don't add this key to the ssh-agent automatically (may be default) - '-o', - 'AddKeysToAgent=no', - // Ignore any keys that have already been added to the ssh-agent - '-o', - 'IdentitiesOnly=yes', - `${username}@${host}`, - command, - ]); - } catch (err) { - throw R.prop('stderr', err); - } - - return R.propOr(null, 'stdout')(output); -} diff --git a/dashboards/examples/deployment-dashboard.json b/dashboards/examples/deployment-dashboard.json deleted file mode 100644 index 595209d9d..000000000 --- a/dashboards/examples/deployment-dashboard.json +++ /dev/null @@ -1,668 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 1, - "hideControls": false, - "links": [], - "rows": [{ - "collapse": false, - "height": "200px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(container_memory_usage_bytes{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}) / 1024^3", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_deployment_spec_replicas", - "refId": "A", - "step": 600 - }], - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_deployment_status_observed_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_deployment_metadata_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "max(kube_deployment_status_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "current replicas", - "refId": "A", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_deployment_status_replicas_unavailable{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "unavailable", - "refId": "C", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_updated{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "updated", - "refId": "D", - "step": 30 - }, - { - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - }], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [{ - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "deployment_namespace", - "options": [], - "query": "label_values(kube_deployment_metadata_generation, namespace)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": null, - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Deployment", - "multi": false, - "name": "deployment_name", - "options": [], - "query": "label_values(kube_deployment_metadata_generation{namespace=\"$deployment_namespace\"}, deployment)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "deployment", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Deployment", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/examples/ingress.json b/dashboards/examples/ingress.json deleted file mode 100644 index 6f332e127..000000000 --- a/dashboards/examples/ingress.json +++ /dev/null @@ -1,685 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROM", - "label": "", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.4.2" - }, - { - "type": "panel", - "id": "grafana-worldmap-panel", - "name": "Worldmap Panel", - "version": "0.0.17" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "annotations": { - "list": [] - }, - "description": "Show stats from the kubernetes nginx ingress", - "editable": true, - "gnetId": 3050, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": 236, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROM}", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(nginx_connections_total{instance=~\"^$instance$\"}[1m])) by (type)", - "format": "time_series", - "interval": "1m", - "intervalFactor": 4, - "legendFormat": "{{type}}", - "metric": "nginx_server_requests", - "refId": "A", - "step": 240 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Server Connections", - "tooltip": { - "msResolution": false, - "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 - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 301, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROM}", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(nginx_responses_total{instance=~\"^$instance$\", server_zone=~\"^$host$\"}[5m])) by (status_code)", - "format": "time_series", - "interval": "5m", - "intervalFactor": 4, - "legendFormat": "{{ status_code }} ", - "metric": "nginx_responses_total", - "refId": "A", - "step": 1200 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Server Requests", - "tooltip": { - "msResolution": false, - "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 - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROM}", - "fill": 1, - "id": 2, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(nginx_bytes_total{instance=~\"^$instance$\", server_zone=~\"^$host$\", server_zone!=\"*\", server_zone!=\"_\"}[1m])) by (server_zone)", - "format": "time_series", - "interval": "5m", - "intervalFactor": 4, - "legendFormat": "{{server_zone}}", - "metric": "nginx_bytes_total", - "refId": "A", - "step": 1200 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Server Bytes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 283, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROM}", - "fill": 1, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(increase(nginx_upstream_responses_total{instance=~\"^$instance$\", upstream =~\"^$upstream$\"}[1m])) by (upstream)", - "format": "time_series", - "interval": "1m", - "intervalFactor": 2, - "legendFormat": "{{upstream}}", - "metric": "nginx_upstream_responses_total", - "refId": "A", - "step": 120 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Upstream Requests", - "tooltip": { - "msResolution": false, - "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 - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROM}", - "fill": 1, - "id": 7, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "nginx_upstream_response_msecs_avg{instance=~\"^$instance$\",upstream=~\"^$upstream$\"}", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "{{ upstream }}", - "metric": "nginx_upstream_response_msecs_avg", - "refId": "A", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Upstream Backend Response", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 303, - "panels": [ - { - "circleMaxSize": 30, - "circleMinSize": 2, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROM}", - "decimals": 0, - "esMetric": "Count", - "hideEmpty": false, - "hideZero": false, - "id": 8, - "initialZoom": 1, - "links": [], - "locationData": "countries", - "mapCenter": "(0°, 0°)", - "mapCenterLatitude": 0, - "mapCenterLongitude": 0, - "maxDataPoints": 1, - "repeat": null, - "showLegend": true, - "span": 12, - "stickyLabels": false, - "targets": [ - { - "dsType": "influxdb", - "expr": "sum(nginx_filterzone_responses_total) by (country)", - "format": "time_series", - "groupBy": [ - { - "params": [ - "$__interval" - ], - "type": "time" - }, - { - "params": [ - "null" - ], - "type": "fill" - } - ], - "intervalFactor": 2, - "legendFormat": "{{country}}", - "metric": "nginx_filterzone_responses_total", - "orderByTime": "ASC", - "policy": "default", - "refId": "A", - "resultFormat": "time_series", - "select": [ - [ - { - "params": [ - "value" - ], - "type": "field" - }, - { - "params": [], - "type": "mean" - } - ] - ], - "step": 21600, - "tags": [] - } - ], - "thresholds": "0,10", - "title": "Worldmap", - "type": "grafana-worldmap-panel", - "unitPlural": "", - "unitSingle": "", - "valueName": "total" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "prometheus", - "nginx" - ], - "templating": { - "list": [ - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROM}", - "hide": 0, - "includeAll": true, - "label": "Instance", - "multi": false, - "name": "instance", - "options": [], - "query": "label_values(nginx_bytes_total, instance)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROM}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": false, - "name": "host", - "options": [], - "query": "label_values(nginx_requests_total{server_zone!=\"*\", server_zone!=\"_\", instance=~\"^$instance$\"}, server_zone)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROM}", - "hide": 0, - "includeAll": true, - "label": "Upstream", - "multi": false, - "name": "upstream", - "options": [], - "query": "label_values(nginx_upstream_bytes_total{instance=~\"^$instance$\"}, upstream)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes nginx ingress stats", - "version": 43 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-capacity-planning-dashboard.json b/dashboards/examples/kubernetes-capacity-planning-dashboard.json deleted file mode 100644 index 4615a1bf8..000000000 --- a/dashboards/examples/kubernetes-capacity-planning-dashboard.json +++ /dev/null @@ -1,921 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "refresh": false, - "rows": [{ - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(rate(node_cpu{mode=\"idle\"}[2m])) * 100", - "hide": false, - "intervalFactor": 10, - "legendFormat": "", - "refId": "A", - "step": 50 - }], - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(node_load1)", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load5)", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load15)", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [{ - "expr": "sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)", - "intervalFactor": 2, - "legendFormat": "memory usage", - "metric": "memo", - "refId": "A", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Buffers)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "memo", - "refId": "B", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Cached)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "memo", - "refId": "C", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_MemFree)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "memo", - "refId": "D", - "step": 10, - "target": "" - } - ], - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "((sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal)) * 100", - "intervalFactor": 2, - "metric": "", - "refId": "A", - "step": 60, - "target": "" - }], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "246px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(rate(node_disk_bytes_read[5m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(rate(node_disk_bytes_written[5m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum(rate(node_disk_io_time_ms[5m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 12, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\"}) - sum(node_filesystem_free{device!=\"rootfs\"})) / sum(node_filesystem_size{device!=\"rootfs\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - }], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "transmitted", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(rate(node_network_receive_bytes{device!~\"lo\"}[5m]))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10, - "target": "" - }], - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "transmitted", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(rate(node_network_transmit_bytes{device!~\"lo\"}[5m]))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10, - "target": "" - }], - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "276px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 11, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 11, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum(kube_pod_info)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Current number of Pods", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_node_status_capacity_pods)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Maximum capacity of pods", - "refId": "B", - "step": 10 - } - ], - "title": "Cluster Pod Utilization", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "100 - (sum(kube_node_status_capacity_pods) - sum(kube_pod_info)) / sum(kube_node_status_capacity_pods) * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 60, - "target": "" - }], - "thresholds": "80, 90", - "title": "Pod Utilization", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Capacity Planning", - "version": 4 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-cluster-health-dashboard.json b/dashboards/examples/kubernetes-cluster-health-dashboard.json deleted file mode 100644 index a68529b56..000000000 --- a/dashboards/examples/kubernetes-cluster-health-dashboard.json +++ /dev/null @@ -1,634 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "refresh": "10s", - "rows": [{ - "collapse": false, - "editable": true, - "height": "254px", - "panels": [{ - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 1, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(up{job=~\"apiserver|kube-scheduler|kube-controller-manager\"} == 0)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Control Plane Components Down", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "Everything UP and healthy", - "value": "null" - }, - { - "op": "=", - "text": "", - "value": "" - } - ], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(ALERTS{alertstate=\"firing\",alertname!=\"DeadMansSwitch\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Alerts Firing", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 3, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(ALERTS{alertstate=\"pending\",alertname!=\"DeadMansSwitch\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "3, 5", - "title": "Alerts Pending", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 4, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "count(increase(kube_pod_container_status_restarts[1h]) > 5)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Crashlooping Pods", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": false, - "title": "Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(kube_node_status_condition{condition=\"Ready\",status!=\"true\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Node Not Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 6, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(kube_node_status_condition{condition=\"DiskPressure\",status=\"true\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Node Disk Pressure", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(kube_node_status_condition{condition=\"MemoryPressure\",status=\"true\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Node Memory Pressure", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 8, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(kube_node_spec_unschedulable)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Nodes Unschedulable", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": false, - "title": "Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Cluster Health", - "version": 9 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-cluster-monitoring.json b/dashboards/examples/kubernetes-cluster-monitoring.json deleted file mode 100644 index 76bd4d7e4..000000000 --- a/dashboards/examples/kubernetes-cluster-monitoring.json +++ /dev/null @@ -1,2079 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - }, - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "3.1.1" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.3.0" - } - ], - "id": null, - "title": "Kubernetes cluster monitoring (via Prometheus)", - "description": "Monitors Kubernetes cluster using Prometheus. Shows overall cluster CPU / Memory / Filesystem usage as well as individual pod, containers, systemd services statistics. Uses cAdvisor metrics only.", - "tags": [ - "kubernetes" - ], - "style": "dark", - "timezone": "browser", - "editable": true, - "hideControls": false, - "sharedCrosshair": false, - "rows": [ - { - "collapse": false, - "editable": true, - "height": "200px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)", - "thresholdLine": false - }, - "height": "200px", - "id": 32, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum (rate (container_network_receive_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "network", - "refId": "A", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "network", - "refId": "B", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Network I/O pressure", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Network I/O pressure" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "180px", - "id": 4, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"}) * 100", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "65, 90", - "title": "Cluster memory usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "180px", - "id": 6, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) / sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"}) * 100", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "65, 90", - "title": "Cluster CPU usage (1m avg)", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "180px", - "id": 7, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]da9$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (container_fs_limit_bytes{device=~\"^/dev/[sv]da9$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) * 100", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "refId": "A", - "step": 10 - } - ], - "thresholds": "65, 90", - "title": "Cluster filesystem usage", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 9, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "20%", - "prefix": "", - "prefixFontSize": "20%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Used", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 10, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"})", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Total", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 11, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": " cores", - "postfixFontSize": "30%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m]))", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Used", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 12, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": " cores", - "postfixFontSize": "30%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"})", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Total", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 13, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]da9$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Used", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "1px", - "id": 14, - "interval": null, - "isNew": true, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "sum (container_fs_limit_bytes{device=~\"^/dev/[sv]da9$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", - "interval": "10s", - "intervalFactor": 1, - "refId": "A", - "step": 10 - } - ], - "thresholds": "", - "title": "Total", - "type": "singlestat", - "valueFontSize": "50%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "showTitle": false, - "title": "Total usage" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 3, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "height": "", - "id": 17, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (pod_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "metric": "container_cpu", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Pods CPU usage (1m avg)", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "none", - "label": "cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "showTitle": false, - "title": "Pods CPU usage" - }, - { - "collapse": true, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 3, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "height": "", - "id": 23, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (systemd_service_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ systemd_service_name }}", - "metric": "container_cpu", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "System services CPU usage (1m avg)", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "none", - "label": "cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "System services CPU usage" - }, - { - "collapse": true, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 3, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "height": "", - "id": 24, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": null, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name=~\"^k8s_.*\",container_name!=\"POD\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (container_name, pod_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "pod: {{ pod_name }} | {{ container_name }}", - "metric": "container_cpu", - "refId": "A", - "step": 10 - }, - { - "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, name, image)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", - "metric": "container_cpu", - "refId": "B", - "step": 10 - }, - { - "expr": "sum (rate (container_cpu_usage_seconds_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", - "metric": "container_cpu", - "refId": "C", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Containers CPU usage (1m avg)", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "none", - "label": "cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Containers CPU usage" - }, - { - "collapse": true, - "editable": true, - "height": "500px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 3, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 20, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (rate (container_cpu_usage_seconds_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ id }}", - "metric": "container_cpu", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "All processes CPU usage (1m avg)", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "none", - "label": "cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "showTitle": false, - "title": "All processes CPU usage" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 25, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}) by (pod_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "metric": "container_memory_usage:sort_desc", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Pods memory usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Pods memory usage" - }, - { - "collapse": true, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 26, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}) by (systemd_service_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ systemd_service_name }}", - "metric": "container_memory_usage:sort_desc", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "System services memory usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "System services memory usage" - }, - { - "collapse": true, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 27, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{image!=\"\",name=~\"^k8s_.*\",container_name!=\"POD\",kubernetes_io_hostname=~\"^$Node$\"}) by (container_name, pod_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "pod: {{ pod_name }} | {{ container_name }}", - "metric": "container_memory_usage:sort_desc", - "refId": "A", - "step": 10 - }, - { - "expr": "sum (container_memory_working_set_bytes{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}) by (kubernetes_io_hostname, name, image)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", - "metric": "container_memory_usage:sort_desc", - "refId": "B", - "step": 10 - }, - { - "expr": "sum (container_memory_working_set_bytes{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}) by (kubernetes_io_hostname, rkt_container_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", - "metric": "container_memory_usage:sort_desc", - "refId": "C", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Containers memory usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Containers memory usage" - }, - { - "collapse": true, - "editable": true, - "height": "500px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 28, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": true, - "targets": [ - { - "expr": "sum (container_memory_working_set_bytes{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) by (id)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "{{ id }}", - "metric": "container_memory_usage:sort_desc", - "refId": "A", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "All processes memory usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "All processes memory usage" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 16, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (pod_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "-> {{ pod_name }}", - "metric": "network", - "refId": "A", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (pod_name)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "<- {{ pod_name }}", - "metric": "network", - "refId": "B", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Pods network I/O (1m avg)", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Pods network I/O" - }, - { - "collapse": true, - "editable": true, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 30, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (container_name, pod_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "-> pod: {{ pod_name }} | {{ container_name }}", - "metric": "network", - "refId": "B", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (container_name, pod_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "<- pod: {{ pod_name }} | {{ container_name }}", - "metric": "network", - "refId": "D", - "step": 10 - }, - { - "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, name, image)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "-> docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", - "metric": "network", - "refId": "A", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, name, image)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "<- docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", - "metric": "network", - "refId": "C", - "step": 10 - }, - { - "expr": "sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "-> rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", - "metric": "network", - "refId": "E", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", - "hide": false, - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "<- rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", - "metric": "network", - "refId": "F", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Containers network I/O (1m avg)", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "Containers network I/O" - }, - { - "collapse": true, - "editable": true, - "height": "500px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1": null, - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2": null, - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 29, - "isNew": true, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sideWidth": 200, - "sort": "current", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum (rate (container_network_receive_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "-> {{ id }}", - "metric": "network", - "refId": "A", - "step": 10 - }, - { - "expr": "- sum (rate (container_network_transmit_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "<- {{ id }}", - "metric": "network", - "refId": "B", - "step": 10 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "All processes network I/O (1m avg)", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 2, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "show": true - }, - "yaxes": [ - { - "format": "Bps", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "title": "All processes network I/O" - } - ], - "time": { - "from": "now-5m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "templating": { - "list": [ - { - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "multi": false, - "name": "Node", - "options": [], - "query": "label_values(kubernetes_io_hostname)", - "refresh": 1, - "type": "query" - } - ] - }, - "annotations": { - "list": [] - }, - "refresh": "10s", - "schemaVersion": 12, - "version": 13, - "links": [], - "gnetId": 315 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-cluster-status-dashboard.json b/dashboards/examples/kubernetes-cluster-status-dashboard.json deleted file mode 100644 index c246729c6..000000000 --- a/dashboards/examples/kubernetes-cluster-status-dashboard.json +++ /dev/null @@ -1,731 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "rows": [{ - "collapse": false, - "height": "129px", - "panels": [{ - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 6, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(up{job=~\"apiserver|kube-scheduler|kube-controller-manager\"} == 0)", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Control Plane UP", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "UP", - "value": "null" - }], - "valueName": "total" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 6, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(ALERTS{alertstate=\"firing\",alertname!=\"DeadMansSwitch\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "3, 5", - "title": "Alerts Firing", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": true, - "title": "Cluster Health", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "168px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 1, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"apiserver\"} == 1) / count(up{job=\"apiserver\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "API Servers UP", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"kube-controller-manager\"} == 1) / count(up{job=\"kube-controller-manager\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "Controller Managers UP", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"kube-scheduler\"} == 1) / count(up{job=\"kube-scheduler\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "Schedulers UP", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 4, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "count(increase(kube_pod_container_status_restarts{namespace=~\"kube-system|tectonic-system\"}[1h]) > 5)", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "1, 3", - "title": "Crashlooping Control Plane Pods", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": true, - "title": "Control Plane Status", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "158px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "sum(100 - (avg by (instance) (rate(node_cpu{job=\"node-exporter\",mode=\"idle\"}[5m])) * 100)) / count(node_cpu{job=\"node-exporter\",mode=\"idle\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "80, 90", - "title": "CPU Utilization", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "((sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal)) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "80, 90", - "title": "Memory Utilization", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\"}) - sum(node_filesystem_free{device!=\"rootfs\"})) / sum(node_filesystem_size{device!=\"rootfs\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "80, 90", - "title": "Filesystem Utilization", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 10, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "100 - (sum(kube_node_status_capacity_pods) - sum(kube_pod_info)) / sum(kube_node_status_capacity_pods) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "80, 90", - "title": "Pod Utilization", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": true, - "title": "Capacity Planning", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Cluster Status", - "version": 3 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-control-plane-status-dashboard.json b/dashboards/examples/kubernetes-control-plane-status-dashboard.json deleted file mode 100644 index 1b5a6798d..000000000 --- a/dashboards/examples/kubernetes-control-plane-status-dashboard.json +++ /dev/null @@ -1,583 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "rows": [{ - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 1, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"apiserver\"} == 1) / sum(up{job=\"apiserver\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "API Servers UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"kube-controller-manager\"} == 1) / sum(up{job=\"kube-controller-manager\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "Controller Managers UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 3, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(up{job=\"kube-scheduler\"} == 1) / sum(up{job=\"kube-scheduler\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "thresholds": "50, 80", - "title": "Schedulers UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 4, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(sum by(instance) (rate(apiserver_request_count{code=~\"5..\"}[5m])) / sum by(instance) (rate(apiserver_request_count[5m]))) * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - }], - "thresholds": "5, 10", - "title": "API Server Request Error Rate", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "0", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 7, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum by(verb) (rate(apiserver_latency_seconds:quantile[5m]) >= 0)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 30 - }], - "title": "API Server Request Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 5, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "cluster:scheduler_e2e_scheduling_latency_seconds:quantile", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - }], - "title": "End to End Scheduling Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "dtdurations", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum by(instance) (rate(apiserver_request_count{code!~\"2..\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Error Rate", - "refId": "A", - "step": 60 - }, - { - "expr": "sum by(instance) (rate(apiserver_request_count[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Request Rate", - "refId": "B", - "step": 60 - } - ], - "title": "API Server Request Rates", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Control Plane Status", - "version": 3 -} \ No newline at end of file diff --git a/dashboards/examples/kubernetes-resource-requests-dashboard.json b/dashboards/examples/kubernetes-resource-requests-dashboard.json deleted file mode 100644 index 6b74c8058..000000000 --- a/dashboards/examples/kubernetes-resource-requests-dashboard.json +++ /dev/null @@ -1,380 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "refresh": false, - "rows": [{ - "collapse": false, - "editable": true, - "height": "300px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "min(sum(kube_node_status_allocatable_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable CPU Cores", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested CPU Cores", - "refId": "B", - "step": 20 - } - ], - "title": "CPU Cores", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "label": "CPU Cores", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance)) / min(sum(kube_node_status_allocatable_cpu_cores) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - }], - "thresholds": "80, 90", - "title": "CPU Cores", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "CPU Cores", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "300px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "min(sum(kube_node_status_allocatable_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable Memory", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested Memory", - "refId": "B", - "step": 20 - } - ], - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "Memory", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 4, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance)) / min(sum(kube_node_status_allocatable_memory_bytes) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - }], - "thresholds": "80, 90", - "title": "Memory", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Memory", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource Requests", - "version": 2 -} \ No newline at end of file diff --git a/dashboards/examples/nodes-dashboard.json b/dashboards/examples/nodes-dashboard.json deleted file mode 100644 index 403a177b4..000000000 --- a/dashboards/examples/nodes-dashboard.json +++ /dev/null @@ -1,777 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "description": "Dashboard to get an overview of one server", - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "links": [], - "refresh": false, - "rows": [{ - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "100 - (avg by (cpu) (irate(node_cpu{mode=\"idle\", instance=\"$server\"}[5m])) * 100)", - "hide": false, - "intervalFactor": 10, - "legendFormat": "{{cpu}}", - "refId": "A", - "step": 50 - }], - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "node_load1{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "node_load5{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "node_load15{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [{ - "expr": "node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory used", - "metric": "", - "refId": "C", - "step": 10 - }, - { - "expr": "node_memory_Buffers{instance=\"$server\"}", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "", - "refId": "E", - "step": 10 - }, - { - "expr": "node_memory_Cached{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "", - "refId": "F", - "step": 10 - }, - { - "expr": "node_memory_MemFree{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "", - "refId": "D", - "step": 10 - } - ], - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "((node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}) / node_memory_MemTotal{instance=\"$server\"}) * 100", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - }], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum by (instance) (rate(node_disk_bytes_read{instance=\"$server\"}[2m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum by (instance) (rate(node_disk_bytes_written{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum by (instance) (rate(node_disk_io_time_ms{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=\"$server\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - }], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "transmitted", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "rate(node_network_receive_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "A", - "step": 10, - "target": "" - }], - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "transmitted", - "yaxis": 2 - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "rate(node_network_transmit_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "B", - "step": 10, - "target": "" - }], - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [{ - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "server", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Nodes", - "version": 2 -} \ No newline at end of file diff --git a/dashboards/examples/nodes.json b/dashboards/examples/nodes.json deleted file mode 100644 index 47340e931..000000000 --- a/dashboards/examples/nodes.json +++ /dev/null @@ -1,872 +0,0 @@ -{ - "__inputs": [ - { - "description": "Prometheus data source", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - } - ], - "__requires": [ - { - "id": "grafana", - "name": "Grafana", - "type": "grafana", - "version": "4.5.0" - }, - { - "id": "graph", - "name": "Graph", - "type": "panel", - "version": "" - }, - { - "id": "prometheus", - "name": "Prometheus", - "type": "datasource", - "version": "1.5.2" - }, - { - "id": "singlestat", - "name": "Singlestat", - "type": "panel", - "version": "" - } - ], - "annotations": { - "list": [] - }, - "description": "Dashboard to get an overview of the nodes (mod of https://grafana.com/dashboards/3140)", - "editable": true, - "gnetId": 3140, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "100 - (avg by (cpu) (irate(node_cpu{mode=\"idle\", instance=~\"^$server$\"}[5m])) * 100)", - "hide": false, - "intervalFactor": 10, - "legendFormat": "{{cpu}}", - "refId": "A", - "step": 50 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Idle cpu", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 9, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node_load1{instance=~\"^$server$\"}", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "node_load5{instance=~\"^$server$\"}", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "node_load15{instance=~\"^$server$\"}", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "node_memory_SwapFree{instance=~\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - } - ], - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_memory_MemTotal{instance=~\"^$server$\"}) - sum(node_memory_MemFree{instance=~\"^$server$\"}) - sum(node_memory_Buffers{instance=~\"^$server$\"}) - sum(node_memory_Cached{instance=~\"^$server$\"})", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory used", - "metric": "", - "refId": "C", - "step": 4 - }, - { - "expr": "sum(node_memory_Buffers{instance=~\"^$server$\"})", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "", - "refId": "E", - "step": 4 - }, - { - "expr": "sum(node_memory_Cached{instance=~\"^$server$\"})", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "", - "refId": "F", - "step": 4 - }, - { - "expr": "sum(node_memory_MemFree{instance=~\"^$server$\"})", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "", - "refId": "D", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": "0", - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "((sum(node_memory_MemTotal{instance=~\"^$server$\"}) - sum(node_memory_MemFree{instance=~\"^$server$\"}) - sum(node_memory_Buffers{instance=~\"^$server$\"}) - sum(node_memory_Cached{instance=~\"^$server$\"})) / sum(node_memory_MemTotal{instance=~\"^$server$\"})) * 100", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Memory usage", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 6, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=~\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (instance) (rate(node_disk_bytes_read{instance=~\"^$server$\"}[2m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 8, - "target": "" - }, - { - "expr": "sum by (instance) (rate(node_disk_bytes_written{instance=~\"^$server$\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 8 - }, - { - "expr": "sum by (instance) (rate(node_disk_io_time_ms{instance=~\"^$server$\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 8 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [ - { - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$server$\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=~\"^$server$\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$server$\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "0.75, 0.9", - "title": "Disk space usage", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 8, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted ", - "yaxis": 2 - } - ], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_receive_bytes{instance=~\"^$server$\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "A", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "alerting": {}, - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": {}, - "id": 10, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted ", - "yaxis": 2 - } - ], - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_transmit_bytes{instance=~\"^$server$\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "B", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "prometheus" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": { - "tags": [], - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": null, - "multi": true, - "name": "server", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Nodes", - "version": 1 -} diff --git a/dashboards/examples/pod_metrics.json b/dashboards/examples/pod_metrics.json deleted file mode 100644 index 1cfaf6895..000000000 --- a/dashboards/examples/pod_metrics.json +++ /dev/null @@ -1,920 +0,0 @@ -{ - "__inputs": [ - { - "description": "Prometheus data source", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - } - ], - "__requires": [ - { - "id": "grafana", - "name": "Grafana", - "type": "grafana", - "version": "4.5.0" - }, - { - "id": "graph", - "name": "Graph", - "type": "panel", - "version": "" - }, - { - "id": "prometheus", - "name": "Prometheus", - "type": "datasource", - "version": "1.5.2" - }, - { - "id": "singlestat", - "name": "Singlestat", - "type": "panel", - "version": "" - } - ], - "annotations": { - "list": [] - }, - "description": "Basic pod (status, container name, ip, ready, scheduled) and container (running, restart, ready, terminated, waiting) information. It doesn't capture container or pod termination/restarts when kubectl pod delete pod is executed. It does capture container restarts when docker kill container is executed. All the stats are accumulated over time, so if something happened in the past, when the time series is set to now, the stats will stil show the past events.", - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": 32, - "links": [], - "rows": [ - { - "collapse": false, - "height": "250", - "panels": [ - { - "content": "

$phase

", - "height": "55px", - "id": 3, - "links": [], - "mode": "html", - "span": 3, - "title": "Status", - "type": "text" - }, - { - "content": "

$container

", - "height": "55px", - "id": 10, - "links": [], - "mode": "html", - "span": 4, - "title": "Container", - "type": "text" - }, - { - "content": "

$pod_ip

", - "height": "55px", - "id": 9, - "links": [], - "mode": "html", - "span": 3, - "title": "IP", - "type": "text" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 1, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 1, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_scheduled{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Scheduled", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Pod Status", - "titleSize": "h5" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_running{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Running", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_restarts{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Restarts", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 1, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_terminated{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Terminated", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_waiting{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Waiting", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 11, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_container_status_running{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Running", - "refId": "A", - "step": 4 - }, - { - "expr": "sum(kube_pod_container_status_restarts{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Restarts", - "refId": "B", - "step": 4 - }, - { - "expr": "sum(kube_pod_container_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Ready", - "refId": "C", - "step": 4 - }, - { - "expr": "sum(kube_pod_container_status_terminated{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Terminated", - "refId": "D", - "step": 4 - }, - { - "expr": "sum(kube_pod_container_status_waiting{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Waiting", - "refId": "E", - "step": 4 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Status", - "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 - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Container Status", - "titleSize": "h5" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [], - "templating": { - "list": [ - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": true, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Pod", - "multi": true, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "100.124.0.7", - "value": "100.124.0.7" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Pod IP", - "multi": false, - "name": "pod_ip", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, pod_ip)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": { - "text": "Running", - "value": "Running" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Phase", - "multi": false, - "name": "phase", - "options": [ - { - "selected": true, - "text": "Running", - "value": "Running" - } - ], - "query": "label_values(kube_pod_status_phase{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, phase)", - "refresh": 0, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "grafana", - "value": "grafana" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Container", - "multi": false, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, container)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Pod + Container Metrics", - "version": 14 -} diff --git a/dashboards/examples/pods-dashboard.json b/dashboards/examples/pods-dashboard.json deleted file mode 100644 index a4b5b962f..000000000 --- a/dashboards/examples/pods-dashboard.json +++ /dev/null @@ -1,373 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 1, - "hideControls": false, - "links": [], - "refresh": false, - "rows": [{ - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": false, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum by(container_name) (container_memory_usage_bytes{pod_name=\"$pod\", container_name=~\"$container\", container_name!=\"POD\"})", - "interval": "10s", - "intervalFactor": 1, - "legendFormat": "Current: {{ container_name }}", - "metric": "container_memory_usage_bytes", - "refId": "A", - "step": 15 - }, - { - "expr": "kube_pod_container_resource_requests_memory_bytes{pod=\"$pod\", container=~\"$container\"}", - "interval": "10s", - "intervalFactor": 2, - "legendFormat": "Requested: {{ container }}", - "metric": "kube_pod_container_resource_requests_memory_bytes", - "refId": "B", - "step": 20 - } - ], - "title": "Memory Usage", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }], - "showTitle": false, - "title": "Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 2, - "isNew": false, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sum by (container_name)(rate(container_cpu_usage_seconds_total{image!=\"\",container_name!=\"POD\",pod_name=\"$pod\"}[1m]))", - "intervalFactor": 2, - "legendFormat": "{{ container_name }}", - "refId": "A", - "step": 30 - }], - "title": "CPU Usage", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }], - "showTitle": false, - "title": "Row", - "titleSize": "h6" - }, - { - "collapse": false, - "editable": true, - "height": "250px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": true, - "avg": true, - "current": true, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "sort_desc(sum by (pod_name) (rate(container_network_receive_bytes_total{pod_name=\"$pod\"}[1m])))", - "intervalFactor": 2, - "legendFormat": "{{ pod_name }}", - "refId": "A", - "step": 30 - }], - "title": "Network I/O", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }], - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [{ - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Pod", - "multi": false, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"$namespace\"}, pod)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Container", - "multi": false, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_info{namespace=\"$namespace\", pod=\"$pod\"}, container)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Pods", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/examples/resource-cpu-requests.json b/dashboards/examples/resource-cpu-requests.json deleted file mode 100644 index 36e06edcc..000000000 --- a/dashboards/examples/resource-cpu-requests.json +++ /dev/null @@ -1,353 +0,0 @@ -{ - "__inputs": [ - { - "description": "Prometheus data source", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - } - ], - "__requires": [ - { - "id": "grafana", - "name": "Grafana", - "type": "grafana", - "version": "4.5.0" - }, - { - "id": "graph", - "name": "Graph", - "type": "panel", - "version": "" - }, - { - "id": "prometheus", - "name": "Prometheus", - "type": "datasource", - "version": "1.5.2" - }, - { - "id": "singlestat", - "name": "Singlestat", - "type": "panel", - "version": "" - } - ], - "annotations": { - "list": [] - }, - "description": "Dashboard to show the resource requests vs allocatable in the cluster (mod of https://grafana.com/dashboards/3149)", - "editable": true, - "gnetId": 3149, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "300", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable_cpu_cores{node=~\"^$host$\"})", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable CPU Cores", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\", container=~\"^$container$\"})", - "intervalFactor": 2, - "legendFormat": "Requested CPU Cores", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Cores", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "CPU Cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\", container=~\"^$container$\"}) / sum(kube_node_status_allocatable_cpu_cores{node=~\"^$host$\"}) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "CPU Cores", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "CPU Cores", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "name": "host", - "options": [], - "query": "label_values(kube_node_status_allocatable_cpu_cores, node)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": true, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Pod", - "multi": true, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\", namespace=~\"^$namespace$\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Container", - "multi": true, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, container)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource CPU Requests", - "version": 1 -} diff --git a/dashboards/examples/resource-memory-requests.json b/dashboards/examples/resource-memory-requests.json deleted file mode 100644 index f91fac881..000000000 --- a/dashboards/examples/resource-memory-requests.json +++ /dev/null @@ -1,353 +0,0 @@ -{ - "__inputs": [ - { - "description": "Prometheus data source", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - } - ], - "__requires": [ - { - "id": "grafana", - "name": "Grafana", - "type": "grafana", - "version": "4.5.0" - }, - { - "id": "graph", - "name": "Graph", - "type": "panel", - "version": "" - }, - { - "id": "prometheus", - "name": "Prometheus", - "type": "datasource", - "version": "1.5.2" - }, - { - "id": "singlestat", - "name": "Singlestat", - "type": "panel", - "version": "" - } - ], - "annotations": { - "list": [] - }, - "description": "Dashboard to show the resource requests vs allocatable in the cluster (mod of https://grafana.com/dashboards/3149)", - "editable": true, - "gnetId": 3149, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "300", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable_memory_bytes{node=~\"^$host$\"})", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable Memory", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\", container=~\"^$container$\"})", - "intervalFactor": 2, - "legendFormat": "Requested Memory", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "Memory", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\", container=~\"^$container$\"}) / sum(kube_node_status_allocatable_memory_bytes{node=~\"^$host$\"}) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Memory", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "name": "host", - "options": [], - "query": "label_values(kube_node_status_allocatable_memory_bytes, node)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": true, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\"}, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Pod", - "multi": true, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\", namespace=~\"^$namespace$\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Container", - "multi": true, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\", namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, container)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource Memory Requests", - "version": 1 -} diff --git a/dashboards/examples/resource-requests.json b/dashboards/examples/resource-requests.json deleted file mode 100644 index 064c5ba87..000000000 --- a/dashboards/examples/resource-requests.json +++ /dev/null @@ -1,452 +0,0 @@ -{ - "__inputs": [ - { - "description": "Prometheus data source", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - } - ], - "__requires": [ - { - "id": "grafana", - "name": "Grafana", - "type": "grafana", - "version": "4.5.0" - }, - { - "id": "graph", - "name": "Graph", - "type": "panel", - "version": "" - }, - { - "id": "prometheus", - "name": "Prometheus", - "type": "datasource", - "version": "1.5.2" - }, - { - "id": "singlestat", - "name": "Singlestat", - "type": "panel", - "version": "" - } - ], - "annotations": { - "list": [] - }, - "description": "Dashboard to show the resource requests vs allocatable in the cluster (mod of https://grafana.com/dashboards/3149)", - "editable": true, - "gnetId": 3149, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "300", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "fill": 1, - "id": 1, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable_cpu_cores{node=~\"^$host$\"})", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable CPU Cores", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\"})", - "intervalFactor": 2, - "legendFormat": "Requested CPU Cores", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Cores", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "CPU Cores", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_cpu_cores{node=~\"^$host$\"}) / sum(kube_node_status_allocatable_cpu_cores{node=~\"^$host$\"}) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "CPU Cores", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "CPU Cores", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "fill": 1, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_node_status_allocatable_memory_bytes{node=~\"^$host$\"})", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable Memory", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\"})", - "intervalFactor": 2, - "legendFormat": "Requested Memory", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "Memory", - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [ - { - "expr": "sum(kube_pod_container_resource_requests_memory_bytes{node=~\"^$host$\"}) / sum(kube_node_status_allocatable_memory_bytes{node=~\"^$host$\"}) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Memory", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": { - "text": "All", - "value": [ - "$__all" - ] - }, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "name": "host", - "options": [], - "query": "label_values(kube_node_status_allocatable_cpu_cores, node)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource CPU + Memory Requests", - "version": 1 -} diff --git a/dashboards/examples/statefulset-dashboard.json b/dashboards/examples/statefulset-dashboard.json deleted file mode 100644 index fb4119783..000000000 --- a/dashboards/examples/statefulset-dashboard.json +++ /dev/null @@ -1,647 +0,0 @@ -{ - "__inputs": [{ - "description": "", - "label": "prometheus", - "name": "DS_PROMETHEUS", - "pluginId": "prometheus", - "pluginName": "Prometheus", - "type": "datasource" - }], - "annotations": { - "list": [] - }, - "editable": true, - "graphTooltip": 1, - "hideControls": false, - "links": [], - "rows": [{ - "collapse": false, - "height": "200px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(container_memory_usage_bytes{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}) / 1024^3", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "targets": [{ - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [{ - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_statefulset_replicas", - "refId": "A", - "step": 600 - }], - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_statefulset_status_observed_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - }, - { - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "targets": [{ - "expr": "max(kube_statefulset_metadata_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - }], - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "avg" - } - ], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": true, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "mode": "time", - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - }], - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "sharedCrosshair": false, - "style": "dark", - "tags": [], - "templating": { - "list": [{ - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "statefulset_namespace", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation, namespace)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": null, - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "StatefulSet", - "multi": false, - "name": "statefulset_name", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation{namespace=\"$statefulset_namespace\"}, statefulset)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "statefulset", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "StatefulSet", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/examples/system.json b/dashboards/examples/system.json deleted file mode 100644 index 84cba155a..000000000 --- a/dashboards/examples/system.json +++ /dev/null @@ -1,1948 +0,0 @@ -{ - "__inputs": [{ - "name": "DS_PROMETHEUS", - "label": "prometheus", - "value": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - }], - "__requires": [{ - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.5.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [{ - "datasource": "${DS_PROMETHEUS}", - "enable": false, - "expr": "ALERTS{instance=~\"^$host$\", alertstate=\"firing\"}", - "iconColor": "rgb(252, 5, 0)", - "name": "Alert", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{alertstate}}", - "titleFormat": "{{ alertname }}" - }, - { - "datasource": "${DS_PROMETHEUS}", - "enable": true, - "expr": "ALERTS{instance=~\"^$host$\",alertstate=\"pending\"}", - "iconColor": "rgb(228, 242, 9)", - "name": "Warning", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{ alertstate }}", - "titleFormat": "{{ alertname }}" - } - ] - }, - "description": "Prometheus for system metrics. \r\nLoad, CPU, RAM, network, process ... (mod of https://grafana.com/dashboards/159)", - "editable": true, - "gnetId": 159, - "graphTooltip": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": "30s", - "rows": [{ - "collapse": false, - "height": "250px", - "panels": [{ - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 1, - "editable": true, - "error": false, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 19, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "s", - "postfixFontSize": "80%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_time{instance=~\"^$host$\"} - node_boot_time{instance=~\"^$host$\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_time%7Balias%3D%5C%22%24host%5C%22%7D%20-%20node_boot_time%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A25%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "300,3600", - "title": "System Uptime", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 25, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "count(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300 - }], - "thresholds": "", - "title": "Virtual CPUs", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 26, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "sum(node_memory_MemAvailable{instance=~\"^$host$\"})", - "interval": "", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_memory_MemAvailable", - "refId": "A", - "step": 30 - }], - "thresholds": "", - "title": "RAM available", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(sum(node_memory_MemAvailable{instance=~\"^$host$\"}) or (sum(node_memory_MemFree{instance=~\"^$host$\"}) + sum(node_memory_Buffers{instance=~\"^$host$\"}) + sum(node_memory_Cached{instance=~\"^$host$\"}))) / sum(node_memory_MemTotal{instance=~\"^$host$\"}) * 100", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_mem", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%20%2F%20node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20*%20100%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-15%2013%3A54%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "90,95", - "title": "Memory Available", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "editable": true, - "error": false, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=~\"^$host$\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"})", - "format": "time_series", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300, - "target": "" - }], - "thresholds": "75,95", - "title": "Disk space usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "260px", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{instance=~\"^$host$\"}[$interval])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"}) or sum(irate(node_cpu{instance=~\"^$host$\"}[5m])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "{{ mode }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2 - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Load 1m", - "color": "#E24D42" - }, - { - "alias": "Load 5m", - "color": "#E0752D" - }, - { - "alias": "Load 15m", - "color": "#E5AC0E" - } - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load1{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 1m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load5{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 5m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load5%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load15{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 15m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load15%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 2, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 6, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#0A437C" - }, - { - "alias": "Available", - "color": "#5195CE" - }, - { - "alias": "Total", - "color": "#052B51", - "legend": false, - "stack": false - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Total", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"}))", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Available", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 29, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Buffers{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Buffers", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Cached{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Distribution", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 24, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Forks", - "color": "#EF843C" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_forks{instance=~\"^$host$\"}[$interval]) or irate(node_forks{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Forks", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Forks", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Processes blocked waiting for I/O to complete", - "color": "#E24D42" - }, - { - "alias": "Processes in runnable state", - "color": "#6ED0E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_running{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes in runnable state", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_blocked{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes blocked waiting for I/O to complete", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_blocked%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Processes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 27, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_context_switches{instance=~\"^$host$\"}[$interval]) or irate(node_context_switches{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Context Switches", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Context Switches", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Interrupts", - "color": "#D683CE" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_intr{instance=~\"^$host$\"}[$interval]) or irate(node_intr{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Interrupts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Interrupts", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Inbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Outbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sort": "min", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600, - "target": "" - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Network Utilization Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#584477" - }, - { - "alias": "Free", - "color": "#AEA2E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapTotal{instance=~\"^$host$\"} - node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 30, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpin{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpin{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpout{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpout{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "system", - "prometheus", - "online", - "home" - ], - "templating": { - "list": [{ - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "5s", - "value": "5s" - }, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [{ - "selected": false, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": true, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 2, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "instance", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "System", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/alerts.json b/dashboards/in-use/alerts.json deleted file mode 100644 index b7019c8a7..000000000 --- a/dashboards/in-use/alerts.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "panel", - "id": "alertlist", - "name": "Alert List", - "version": "" - }, - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": 250, - "panels": [ - { - "id": 2, - "limit": 10, - "links": [], - "onlyAlertsOnDashboard": false, - "show": "current", - "sortOrder": 1, - "span": 12, - "stateFilter": [], - "title": "Current Alerts", - "type": "alertlist" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 223, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 50 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "The memory used within the Kubernetes cluster is above the defined threshold.", - "name": "Cluster Memory Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "description": "Percentage of memory used across the cluster.", - "fill": 1, - "id": 1, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal) * 100 ", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "Percentage memory used", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 50 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Cluster Memory Used", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Alerts", - "version": 8 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-capacity-planning.json b/dashboards/in-use/kubernetes-capacity-planning.json deleted file mode 100644 index b317326cf..000000000 --- a/dashboards/in-use/kubernetes-capacity-planning.json +++ /dev/null @@ -1,1078 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_cpu{mode=\"idle\"}[2m])) * 100", - "hide": false, - "intervalFactor": 10, - "legendFormat": "", - "refId": "A", - "step": 50 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_load1)", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load5)", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "sum(node_load15)", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)", - "intervalFactor": 2, - "legendFormat": "memory usage", - "metric": "memo", - "refId": "A", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Buffers)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "memo", - "refId": "B", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_Cached)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "memo", - "refId": "C", - "step": 10, - "target": "" - }, - { - "expr": "sum(node_memory_MemFree)", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "memo", - "refId": "D", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "((sum(node_memory_MemTotal) - sum(node_memory_MemFree) - sum(node_memory_Buffers) - sum(node_memory_Cached)) / sum(node_memory_MemTotal)) * 100", - "intervalFactor": 2, - "metric": "", - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "246px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_disk_bytes_read[5m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum(rate(node_disk_bytes_written[5m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum(rate(node_disk_io_time_ms[5m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 12, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(node_filesystem_size{device!=\"rootfs\"}) - sum(node_filesystem_free{device!=\"rootfs\"})) / sum(node_filesystem_size{device!=\"rootfs\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_network_receive_bytes{device!~\"lo\"}[5m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_network_transmit_bytes{device!~\"lo\"}[5m]))", - "format": "time_series", - "hide": false, - "intervalFactor": 2, - "legendFormat": "", - "refId": "B", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "276px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 11, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 11, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(kube_pod_info)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Current number of Pods", - "refId": "A", - "step": 10 - }, - { - "expr": "sum(kube_node_status_capacity_pods)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Maximum capacity of pods", - "refId": "B", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Cluster Pod Utilization", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "100 - (sum(kube_node_status_capacity_pods) - sum(kube_pod_info)) / sum(kube_node_status_capacity_pods) * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Pod Utilization", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Capacity Planning", - "version": 3 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-control-plane-status.json b/dashboards/in-use/kubernetes-control-plane-status.json deleted file mode 100644 index fab68128c..000000000 --- a/dashboards/in-use/kubernetes-control-plane-status.json +++ /dev/null @@ -1,320 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - }, - { - "type": "panel", - "id": "table", - "name": "Table", - "version": "" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 1, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(up{job=\"kubernetes-apiservers\"} == 1) / sum(up{job=\"kubernetes-apiservers\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "50, 80", - "title": "API Servers UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(up{job=\"kubernetes-nodes\"} == 1) / sum(up{job=\"kubernetes-nodes\"})) * 100", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "50, 80", - "title": "Nodes UP", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "columns": [], - "datasource": "${DS_PROMETHEUS}", - "fontSize": "100%", - "id": 9, - "links": [], - "pageSize": null, - "scroll": true, - "showHeader": true, - "sort": { - "col": 0, - "desc": true - }, - "span": 6, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "link": false, - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Instance", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 0, - "pattern": "instance", - "thresholds": [], - "type": "number", - "unit": "none" - } - ], - "targets": [ - { - "expr": "sum(up{job=\"kubernetes-nodes\"}) by (instance)", - "format": "table", - "hide": false, - "instant": true, - "intervalFactor": 2, - "refId": "A" - } - ], - "title": "Nodes Up", - "transform": "table", - "type": "table" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Control Plane Status", - "version": 4 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-deployments.json b/dashboards/in-use/kubernetes-deployments.json deleted file mode 100644 index a4e32d8e4..000000000 --- a/dashboards/in-use/kubernetes-deployments.json +++ /dev/null @@ -1,822 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "200px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}) / 1024^3", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",job!=\"kubernetes-apiservers\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$deployment_namespace\",pod_name=~\"$deployment_name.*\",job!=\"kubernetes-apiservers\"}[3m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_deployment_spec_replicas", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_status_observed_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_deployment_metadata_generation{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "max(kube_deployment_status_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "current replicas", - "refId": "A", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_available{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_deployment_status_replicas_unavailable{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "unavailable", - "refId": "C", - "step": 30 - }, - { - "expr": "min(kube_deployment_status_replicas_updated{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "updated", - "refId": "D", - "step": 30 - }, - { - "expr": "max(kube_deployment_spec_replicas{deployment=\"$deployment_name\",namespace=\"$deployment_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".*", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "deployment_namespace", - "options": [], - "query": "label_values(kube_deployment_metadata_generation, namespace)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": null, - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Deployment", - "multi": false, - "name": "deployment_name", - "options": [], - "query": "label_values(kube_deployment_metadata_generation{namespace=\"$deployment_namespace\"}, deployment)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "deployment", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Deployments", - "version": 6 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-pods.json b/dashboards/in-use/kubernetes-pods.json deleted file mode 100644 index 1439b1d92..000000000 --- a/dashboards/in-use/kubernetes-pods.json +++ /dev/null @@ -1,1623 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "", - "editable": true, - "gnetId": null, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": null, - "panels": [ - { - "content": "

$phase

", - "height": "55px", - "id": 3, - "links": [], - "mode": "html", - "span": 4, - "title": "Status", - "type": "text" - }, - { - "content": "

$pod_ip

", - "height": "55px", - "id": 9, - "links": [], - "mode": "html", - "span": 4, - "title": "IP", - "type": "text" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_status_scheduled{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Scheduled", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 18, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",pod_name=~\"$pod\",job!=\"kubernetes-apiservers\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "decbytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 19, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$namespace\",pod_name=~\"$pod\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Current Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 20, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$namespace\",pod_name=~\"$pod\"}[2m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$namespace\",pod_name=~\"$pod\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg Network", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "#299c46", - "rgba(237, 129, 40, 0.89)", - "#d44a3a" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "150px", - "id": 21, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) + sum(rate(container_fs_reads_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m]))", - "format": "time_series", - "intervalFactor": 2, - "refId": "A" - } - ], - "thresholds": "", - "title": "Avg Disk", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Pod Status", - "titleSize": "h5" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 14, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{pod_name=~\"^$pod$\",job!=\"kubernetes-nodes\"}[2m])) by (pod_name)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Pod NW Transmit", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 13, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": false, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_network_receive_bytes_total{pod_name=~\"^$pod$\",job!=\"kubernetes-nodes\"}[2m])) by (pod_name)", - "format": "time_series", - "instant": false, - "intervalFactor": 1, - "legendFormat": "{{ pod_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Pod NW Receive", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_running{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Running", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_restarts{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Restarts", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 1, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_ready{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Ready", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_terminated{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Terminated", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(kube_pod_container_status_waiting{namespace=~\"^$namespace$\", pod=~\"^$pod$\"})", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 60 - } - ], - "thresholds": "", - "title": "Waiting", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Container Status", - "titleSize": "h5" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 12, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "repeat": "container", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=~\"^$namespace$\",pod_name=~\"^$pod$\",container_name!=\"POD\",job!=\"kubernetes-apiservers\"}) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Actual: {{ container_name }}", - "refId": "A" - }, - { - "expr": "kube_pod_container_resource_requests_memory_bytes{pod=~\"^$pod$\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Requested: {{ container }}", - "refId": "B" - }, - { - "expr": "kube_pod_container_resource_limits_memory_bytes{pod=~\"^$pod$\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "Limits: {{ container }}", - "refId": "C" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Memory Usage", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name) ", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container CPU Usage Seconds", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 16, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_writes_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Disk Write", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 17, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(container_fs_reads_bytes_total{namespace=\"$namespace\",container_name!=\"POD\",job!=\"kubernetes-apiservers\",pod_name=~\"^$pod$\"}[2m])) by (container_name)", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ container_name }}", - "refId": "A" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Container Disk Read", - "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": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Namespace", - "multi": false, - "name": "namespace", - "options": [], - "query": "label_values(kube_pod_info, namespace)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Pod", - "multi": false, - "name": "pod", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\"}, pod)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Pod IP", - "multi": false, - "name": "pod_ip", - "options": [], - "query": "label_values(kube_pod_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, pod_ip)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Phase", - "multi": false, - "name": "phase", - "options": [], - "query": "query_result(kube_pod_status_phase{namespace=~\"^$namespace$\", pod=~\"^$pod$\"} == 1)", - "refresh": 2, - "regex": "/.*phase=\"(.+?)\".*/", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - }, - { - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 2, - "includeAll": false, - "label": "Container", - "multi": false, - "name": "container", - "options": [], - "query": "label_values(kube_pod_container_info{namespace=~\"^$namespace$\", pod=~\"^$pod$\"}, container)", - "refresh": 2, - "regex": "", - "sort": 1, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-15m", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Kubernetes Pods", - "version": 27 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-resource-requests.json b/dashboards/in-use/kubernetes-resource-requests.json deleted file mode 100644 index cfa47c2dc..000000000 --- a/dashboards/in-use/kubernetes-resource-requests.json +++ /dev/null @@ -1,466 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [CPU resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu) in the cluster.\nFor comparison the total [allocatable CPU cores](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(sum(kube_node_status_allocatable_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable CPU Cores", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested CPU Cores", - "refId": "B", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Cores", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "CPU Cores", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(sum(kube_pod_container_resource_requests_cpu_cores) by (instance)) / min(sum(kube_node_status_allocatable_cpu_cores) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "CPU Cores", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "CPU Cores", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "description": "This represents the total [memory resource requests](https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-memory) in the cluster.\nFor comparison the total [allocatable memory](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node-allocatable.md) is also shown.", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(sum(kube_node_status_allocatable_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Allocatable Memory", - "refId": "A", - "step": 20 - }, - { - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance))", - "hide": false, - "intervalFactor": 2, - "legendFormat": "Requested Memory", - "refId": "B", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "Memory", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 4, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(sum(kube_pod_container_resource_requests_memory_bytes) by (instance)) / min(sum(kube_node_status_allocatable_memory_bytes) by (instance)) * 100", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 240 - } - ], - "thresholds": "80, 90", - "title": "Memory", - "transparent": false, - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Memory", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes Resource Requests", - "version": 2 -} \ No newline at end of file diff --git a/dashboards/in-use/kubernetes-statefulsets.json b/dashboards/in-use/kubernetes-statefulsets.json deleted file mode 100644 index 4c1b1ded2..000000000 --- a/dashboards/in-use/kubernetes-statefulsets.json +++ /dev/null @@ -1,802 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": "200px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 8, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "cores", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_cpu_usage_seconds_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "format": "time_series", - "interval": "", - "intervalFactor": 2, - "legendFormat": "", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "CPU", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "GB", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(container_memory_usage_bytes{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}) / 1024^3", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Memory", - "type": "singlestat", - "valueFontSize": "110%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "Bps", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "expr": "sum(rate(container_network_transmit_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m])) + sum(rate(container_network_receive_bytes_total{namespace=\"$statefulset_namespace\",pod_name=~\"$statefulset_name.*\"}[3m]))", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Network", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "100px", - "panels": [ - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": false - }, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "metric": "kube_statefulset_replicas", - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Desired Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 6, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "format": "time_series", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Available Replicas", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 3, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_status_observed_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Observed Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "id": 2, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "max(kube_statefulset_metadata_generation{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "refId": "A", - "step": 600 - } - ], - "thresholds": "", - "title": "Metadata Generation", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "350px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 1, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "min(kube_statefulset_status_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "available", - "refId": "B", - "step": 30 - }, - { - "expr": "max(kube_statefulset_replicas{statefulset=\"$statefulset_name\",namespace=\"$statefulset_namespace\"}) without (instance, pod)", - "intervalFactor": 2, - "legendFormat": "desired", - "refId": "E", - "step": 30 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Replicas", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "kubernetes" - ], - "templating": { - "list": [ - { - "allValue": "None", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Namespace", - "multi": false, - "name": "statefulset_namespace", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation, namespace)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "None", - "type": "query", - "useTags": false - }, - { - "allValue": "None", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "StatefulSet", - "multi": false, - "name": "statefulset_name", - "options": [], - "query": "label_values(kube_statefulset_metadata_generation{namespace=\"$statefulset_namespace\"}, statefulset)", - "refresh": 2, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "statefulset", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Kubernetes StatefulSets", - "version": 4 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-cross-server-graphs.json b/dashboards/in-use/mysql-cross-server-graphs.json deleted file mode 100644 index e7f8881af..000000000 --- a/dashboards/in-use/mysql-cross-server-graphs.json +++ /dev/null @@ -1,926 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 3, - "legend": { - "avg": false, - "current": false, - "max": false, - "min": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_connections{alias=~\"$host\"}[$interval]) or irate(mysql_global_status_connections{alias=~\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 4, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=~\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=~\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_queries%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load1{alias=~\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [ - { - "colorMode": "custom", - "line": true, - "lineColor": "rgb(241, 34, 15)", - "op": "gt", - "value": 15 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 7, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "(node_memory_MemTotal{alias=~\"$host\"} - (node_memory_MemAvailable{alias=~\"$host\"} or (node_memory_MemFree{alias=~\"$host\"} + node_memory_Buffers{alias=~\"$host\"} + node_memory_Cached{alias=~\"$host\"}))) / node_memory_MemTotal{alias=~\"$host\"} * 100", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [ - { - "colorMode": "custom", - "line": true, - "lineColor": "rgb(248, 8, 48)", - "op": "gt", - "value": 95 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(mysql_global_status_bytes_received{alias=~\"$host\"}[$interval]) + rate(mysql_global_status_bytes_sent{alias=~\"$host\"}[$interval])) or (irate(mysql_global_status_bytes_received{alias=~\"$host\"}[5m]) + irate(mysql_global_status_bytes_sent{alias=~\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Traffic", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_receive_bytes{alias=~\"$host\", device!=\"lo\"}[$interval]) + rate(node_network_transmit_bytes{alias=~\"$host\", device!=\"lo\"}[$interval])) by (alias) or sum(irate(node_network_receive_bytes{alias=~\"$host\", device!=\"lo\"}[5m]) + irate(node_network_transmit_bytes{alias=~\"$host\", device!=\"lo\"}[5m])) by (alias)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ alias }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "height": "0", - "id": 9, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_version_info{alias=~\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "{{ alias }} | {{ version }} | {{ version_comment }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_uname_info%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2014%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Info", - "tooltip": { - "msResolution": false, - "shared": false, - "sort": 0, - "value_type": "cumulative" - }, - "transparent": true, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": false, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "height": "0", - "id": 5, - "legend": { - "alignAsTable": true, - "avg": false, - "current": false, - "hideEmpty": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "sort": null, - "sortDesc": null, - "total": false, - "values": false - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_uname_info{alias=~\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "{{ alias }} | Hostname: {{ nodename }} | Kernel: {{ release }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_uname_info%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2014%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Info", - "tooltip": { - "msResolution": false, - "shared": false, - "sort": 0, - "value_type": "cumulative" - }, - "transparent": true, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": false, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Cross-Server Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "OS", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "regex": "", - "type": "interval" - }, - { - "allFormat": "pipe", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "multiFormat": "pipe", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-3h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Cross Server Graphs | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-disk-performance.json b/dashboards/in-use/mysql-disk-performance.json deleted file mode 100644 index ef584d7a3..000000000 --- a/dashboards/in-use/mysql-disk-performance.json +++ /dev/null @@ -1,1000 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "content": "You can click on an individual disk device on the legend to filter on it or multiple ones by holding Alt button.", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "height": "50px", - "id": 8, - "links": [], - "mode": "text", - "span": 12, - "style": {}, - "title": "", - "transparent": true, - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ms", - "label": "", - "logBase": 2, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 15, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_reads_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_writes_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "iops", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 16, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_bytes_read{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_bytes_read{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_bytes_written{device=~\"$device\", alias=\"$host\"}[$interval]) or irate(node_disk_bytes_written{device=~\"$device\", alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Bandwidth", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_read_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A7%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_write_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A7%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 17, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_io_time_ms{device=~\"$device\", alias=\"$host\"}[$interval])/1000 or irate(node_disk_io_time_ms{device=~\"$device\", alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_io_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Utilization", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(1 + rate(node_disk_reads_merged{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (1 + irate(node_disk_reads_merged{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read Ratio: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_reads_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(1 + rate(node_disk_writes_merged{device=~\"$device\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[$interval])) or (1 + irate(node_disk_writes_merged{device=~\"$device\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device=~\"$device\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write Ratio: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2B%20rate(node_disk_writes_merged%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Operations Merge Ratio", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - "Read IO size: sdb": "#2F575E", - "Read: sdb": "#3F6833" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_sectors_read{alias=\"$host\", device=~\"$device\"}[$interval]) * 512 / rate(node_disk_reads_completed{alias=\"$host\", device=~\"$device\"}[$interval]) or irate(node_disk_sectors_read{alias=\"$host\", device=~\"$device\"}[5m]) * 512 / irate(node_disk_reads_completed{alias=\"$host\", device=~\"$device\"}[5m]) ", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read size: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_read%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_disk_sectors_written{alias=\"$host\", device=~\"$device\"}[$interval]) * 512 / rate(node_disk_writes_completed{alias=\"$host\", device=~\"$device\"}[$interval]) or irate(node_disk_sectors_written{alias=\"$host\", device=~\"$device\"}[5m]) * 512 / irate(node_disk_writes_completed{alias=\"$host\", device=~\"$device\"}[5m]) ", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write size: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_sectors_written%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk IO Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Disk Stats", - "titleSize": "h6" - }, - { - "collapse": true, - "height": "250px", - "panels": [ - { - "content": "Disk Performance Dashboard is designed to provide quick overview of disk IO utilization and performance.\n\n`Disk Latency` - Shows average latency for Reads and Writes IO Devices. Higher than typical latency for highly loaded storage indicates saturation (overload) and is frequent cause of performance problems. Higher than normal latency also can indicate internal storage problems.\n\n`Disk Operations` - Shows amount of physical IOs (reads and writes) different devices are serving. Spikes in number of IOs served often corresponds to performance problems due to IO subsystem overload.\n\n`Disk Bandwidth` - Shows volume of reads and writes the storage is handling. This can be better measure of IO capacity usage for network attached and SSD storage as it is often bandwidth limited. Amount of data being written to the disk can be used to estimate Flash storage life time.\n\n`Disk Load` - Disk Load shows how much disk was loaded for reads or writes as average number of outstanding requests at different period of time. High disk load is a good measure of actual storage utilization. Different storage types handle load differently - some will show latency increases on low loads others can handle higher load with no problems.\n\n`Disk IO Utilization` - Shows disk Utilization as percent of the time when there was at least one IO request in flight. It is designed to match utilization available in iostat tool. It is not very good measure of true IO Capacity Utilization. Consider looking at IO latency and Disk Load Graphs instead.\n\n`Disk Operations Merge Ratio` - Shows how effectively Operating System is able to merge logical IO requests into physical requests. This is a good measure of the IO locality which can be used for workload characterization. \n\n`Disk IO Size` - Shows average size of a single disk operation.", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "id": 19, - "isNew": true, - "links": [], - "mode": "markdown", - "span": 12, - "style": {}, - "title": "", - "type": "text" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "HELP", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Device", - "multi": true, - "multiFormat": "regex values", - "name": "device", - "options": [], - "query": "label_values(node_disk_reads_completed{alias=\"$host\", device!~\"dm-.+\"}, device)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Disk Performance | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-galera-graphs.json b/dashboards/in-use/mysql-galera-graphs.json deleted file mode 100644 index d749b0d11..000000000 --- a/dashboards/in-use/mysql-galera-graphs.json +++ /dev/null @@ -1,1150 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_local_recv_queue{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Receive Queue", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_local_send_queue{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Send Queue", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Replication Queues", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_cluster_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Cluster Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_recv{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_sent{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_flow_control_paused{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "FC Messages Paused", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Flow Control", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Flow Control. This graph shows the number of FC_PAUSE events sent/received. They are sent by a node when its replication queue gets too full. If a node is sending out FC messages it indicates the problem.", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "id": 46, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_local_cert_failures{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_local_cert_failures{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Local Cert Failures", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_local_bf_aborts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_local_bf_aborts{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Local Bf Aborts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writing Conflicts", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Writing Conflicts. This graphs shows the number of local transactions being committed on this node that failed certification (some other node had a commit that conflicted with ours) – client received deadlock error on commit and also the number of local transactions in flight on this node that were aborted because they locked something an applier thread needed – deadlock error anywhere in an open transaction. The spikes on the graph may indicate writing to the same table potentially the same rows from 2 nodes.\n", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "id": 43, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 0, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_apply_window{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Apply Window", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_commit_window{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Commit Window", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_wsrep_cert_deps_distance{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Cert Deps Distance", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Parallelization Efficiency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "Galera Parallelization Efficiency. This graph shows the average distances between highest and lowest seqno that are concurrently applied, commited and can be possibly applied in parallel (potential degree of parallelization).\n", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "id": 44, - "links": [], - "mode": "markdown", - "span": 6, - "style": {}, - "title": "", - "type": "text" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Transactions Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Transactions Replicated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Count", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_wsrep_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[5m]) / irate(mysql_global_status_wsrep_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Incoming Transaction Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[5m]) / irate(mysql_global_status_wsrep_replicated{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Replicating Transaction Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_threads_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Writeset Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_wsrep_received_bytes{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_wsrep_replicated_bytes{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Replicated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Galera Network Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Galera Graphs", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "MySQL", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Galera Graphs | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-innodb-metrics.json b/dashboards/in-use/mysql-innodb-metrics.json deleted file mode 100644 index 93338b5cd..000000000 --- a/dashboards/in-use/mysql-innodb-metrics.json +++ /dev/null @@ -1,2164 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": { - "Max Checkpoint Age": "#BF1B00", - "Uncheckpointed Bytes": "#E0752D" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 19, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Max Checkpoint Age", - "color": "#BF1B00", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_checkpoint_age{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Uncheckpointed Bytes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_checkpoint_max_age{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Checkpoint Age", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Checkpoint Age", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "130px", - "id": 4, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_buffer_pool_size{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_innodb_buffer_pool_size%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-3%206%3A28%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "90,95", - "title": "InnoDB Buffer Pool Size", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "128px", - "id": 5, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "repeat": null, - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(mysql_global_variables_innodb_buffer_pool_size{alias=\"$host\"} * 100) / on (alias) node_memory_MemTotal{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22(mysql_global_variables_innodb_buffer_pool_size%7Balias%3D%5C%22%24host%5C%22%7D%20*%20100)%20%2F%20on%20(alias)%20node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A15%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "40,80", - "title": "Buffer Pool Size of Total RAM", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_max_trx_id{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_max_trx_id{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "InnoDB Transactions", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_history_list_length{alias=\"$host\"} or mysql_info_schema_innodb_metrics_transaction_trx_rseg_history_len{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "History Length", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_max_purge_lag{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Purge Lag", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Transactions", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 37, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Total Size of InnoDB Log Files", - "bars": false, - "color": "#E24D42", - "fill": 0, - "lines": true - }, - { - "alias": "Data Written", - "color": "#E0752D" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_innodb_os_log_written{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Data Written", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_innodb_log_files_in_group{alias=\"$host\"} * mysql_global_variables_innodb_log_file_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Total Size of InnoDB Log Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "InnoDB Log File Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_reads{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_reads{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Reads", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_data_fsyncs{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_data_fsyncs{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Fsyncs", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_max_trx_id%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_log_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_log_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Log Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_history_list_length%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2013%3A14%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": { - "Avg Row Lock Wait Time": "#BF1B00" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Avg Row Lock Wait Time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Row Lock Waits", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[$interval])/1000 or irate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[5m])/1000", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Row Lock Wait Load", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[$interval])/rate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_lock_time{alias=\"$host\"}[5m])/irate(mysql_global_status_innodb_row_lock_waits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Avg Row Lock Wait Time", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Lock Time", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "ms" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "General", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_buffer_pool_bytes_data{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Total", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_buffer_pool_bytes_dirty{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Data Dirty", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Content", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_buffer_pool_pages{alias=\"$host\", state!=\"dirty\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Pages", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_created{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_created{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Created", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_read{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_read{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Read", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_pages_written{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_pages_written{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Written", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_buffer_pool_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_buffer_pool_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_buffer_pool_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_buffer_pool_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Buffer Pool Requests", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Buffer Pool", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": { - "Uncheckpointed Bytes": "#E0752D" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_innodb_ibuf_segment_size{alias=\"$host\"} * mysql_global_status_innodb_page_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Allocated", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(mysql_global_status_innodb_ibuf_segment_size{alias=\"$host\"} - mysql_global_status_innodb_ibuf_free_list{alias=\"$host\"})*mysql_global_status_innodb_page_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_checkpoint_age%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Change Buffer", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merges{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merges{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merges", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_inserts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_inserts{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Inserts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_deletes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_deletes{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Deletes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_ibuf_merged_delete_marks{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_ibuf_merged_delete_marks{alias=\"$host\"}[5m]) or rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Merged Delete Marks", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_read%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Change Buffer Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Change/Insert Buffer", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 44, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_info_schema_innodb_metrics_recovery_log_lsn_current{alias=\"$host\"}*0 + mysql_global_variables_innodb_log_buffer_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "mysql_info_schema_innodb_metrics_recovery_log_lsn_current{alias=\"$host\"} - mysql_info_schema_innodb_metrics_recovery_log_lsn_last_flush{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Log Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "bytes", - "short" - ], - "yaxes": [ - { - "format": "bytes", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 43, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Ibuf Merge Ratio", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Insert", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Delete", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Delete Mark", - "refId": "C", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Merges", - "refId": "D", - "step": 300 - }, - { - "expr": "(rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[$interval])+rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[$interval])+rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[$interval]))/rate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[$interval]) or (irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_insert_total{alias=\"$host\"}[5m])+irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_total{alias=\"$host\"}[5m])+irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_delete_mark_total{alias=\"$host\"}[5m]))/irate(mysql_info_schema_innodb_metrics_change_buffer_ibuf_merges_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Ibuf Merge Ratio", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Change Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "short" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_upd_exist_or_extern_records_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_upd_exist_or_extern_records_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Updates Purged", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_del_mark_records_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_del_mark_records_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Deletes Purged", - "metric": "", - "refId": "A", - "step": 300 - }, - { - "expr": "rate(mysql_info_schema_innodb_metrics_purge_purge_undo_log_pages_total{alias=\"$host\"}[$interval]) or irate(mysql_info_schema_innodb_metrics_purge_purge_undo_log_pages_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Pages Purged", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Purge Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "short" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - }, - { - "aliasColors": { - "Avg Row Lock Wait Time": "#BF1B00" - }, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 1, - "grid": { - "leftLogBase": 1, - "leftMax": null, - "leftMin": 0, - "rightLogBase": 1, - "rightMax": null, - "rightMin": 0 - }, - "id": 47, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": true, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_info_schema_innodb_metrics_transaction_trx_rw_commits_total[$interval])/rate(mysql_global_status_innodb_log_writes[$interval]) or irate(mysql_info_schema_innodb_metrics_transaction_trx_rw_commits_total[5m])/irate(mysql_global_status_innodb_log_writes[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Group Commit Batch Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_data%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Group Commit Batch Size", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "x-axis": true, - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "y-axis": true, - "y_formats": [ - "short", - "ms" - ], - "yaxes": [ - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Performance", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "MySQL", - "Percona" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL InnoDB Metrics | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-myisam-metrics.json b/dashboards/in-use/mysql-myisam-metrics.json deleted file mode 100644 index 44dc9d9b7..000000000 --- a/dashboards/in-use/mysql-myisam-metrics.json +++ /dev/null @@ -1,588 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "text", - "name": "Text", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Reads", - "fill": 0 - }, - { - "alias": "Key Writes", - "fill": 0, - "transform": "negative-Y" - }, - { - "alias": "Key Write Requests", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_reads{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_reads{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Reads", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Read Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_writes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_writes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Writes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Write Requests", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Indexes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Blocks Not Flushed", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_key_buffer_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Buffer Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_key_buffer_size{alias=\"$host\"} - mysql_global_status_key_blocks_unused{alias=\"$host\"} * mysql_global_variables_key_cache_block_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Blocks Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_key_blocks_not_flushed{alias=\"$host\"} * mysql_global_variables_key_cache_block_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Blocks Not Flushed", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_pages_written%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A2%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Key Cache", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Key Reads", - "fill": 0 - }, - { - "alias": "Key Writes", - "fill": 0, - "transform": "negative-Y" - }, - { - "alias": "Key Write Requests", - "transform": "negative-Y" - } - ], - "spaceLength": 10, - "span": 7, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_reads{alias=\"$host\"}[$interval]) / rate(mysql_global_status_key_read_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_reads{alias=\"$host\"}[5m]) / irate(mysql_global_status_key_read_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Read Ratio", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_key_writes{alias=\"$host\"}[$interval]) / rate(mysql_global_status_key_write_requests{alias=\"$host\"}[$interval]) or irate(mysql_global_status_key_writes{alias=\"$host\"}[5m]) / irate(mysql_global_status_key_write_requests{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Key Write Ratio", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_innodb_buffer_pool_pages_free%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-2%207%3A21%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MyISAM Key Buffer Performance", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "content": "The `Key_reads/Key_read_requests` ratio should normally be less than 0.01.\n\nThe `Key_writes/Key_write_requests` ratio is usually near 1 if you are using mostly updates and deletes, but might be much smaller if you tend to do updates that affect many rows at the same time or if you are using the `DELAY_KEY_WRITE` table option.", - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "height": "", - "id": 23, - "links": [], - "mode": "markdown", - "span": 5, - "style": {}, - "title": "", - "type": "text" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "InnoDB Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL MyISAM Metrics | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-overview.json b/dashboards/in-use/mysql-overview.json deleted file mode 100644 index 12e2c918f..000000000 --- a/dashboards/in-use/mysql-overview.json +++ /dev/null @@ -1,2742 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "270px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Max Connections", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 8, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_connections{alias=\"$host\"}[$interval]) or irate(mysql_global_status_connections{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_max_used_connections{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Used Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_max_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_max_connections{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Max Connections", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_max_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 1, - "editable": true, - "error": false, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "130px", - "id": 12, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "s", - "postfixFontSize": "80%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_uptime{alias=\"$host\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_uptime%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A42%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "300,3600", - "title": "MySQL Uptime", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "short", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "128px", - "id": 13, - "interval": "$interval", - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [ - { - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_queries%7Balias%3D%5C%22%24host%5C%22%7D%20%2F%20mysql_global_status_uptime%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": "35,75", - "title": "Current QPS", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 10, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Threads Running", - "color": "#E24D42" - }, - { - "alias": "Threads Connected", - "color": "#EAB839" - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_connected{alias=\"$host\"}", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Connected", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_connected%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_running{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Running", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A9%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Active Threads", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 11, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Threads Created", - "fill": 0 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_thread_cache_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Thread Cache Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_variables_thread_cache_size%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_threads_cached{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_threads_cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_threads_created{alias=\"$host\"}[$interval]) or irate(mysql_global_status_threads_created{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Threads Created", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_threads_created%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-8-27%208%3A18%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Thread Cache", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 32, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_table_locks_immediate{alias=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_immediate{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Locks Immediate", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_table_locks_waited{alias=\"$host\"}[$interval]) or irate(mysql_global_status_table_locks_waited{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Locks Waited", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Table Locks", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_tables%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_disk_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_disk_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Disk Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_disk_tables%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_created_tmp_files{alias=\"$host\"}[$interval]) or irate(mysql_global_status_created_tmp_files{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Created Tmp Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_created_tmp_files%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-24%2011%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Temporary Objects", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_full_join{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_join{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Full Join", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_full_join%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_full_range_join{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_full_range_join{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Full Range Join", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_full_range_join%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_range{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_range{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Range", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_range%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_range_check{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_range_check{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Range Check", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_range_check%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_select_scan{alias=\"$host\"}[$interval]) or irate(mysql_global_status_select_scan{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Select Scan", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_select_scan%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A39%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Select Types", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 30, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_rows{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_rows{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Rows", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_rows%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A36%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_range{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_range{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Range", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_range%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A36%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_merge_passes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_merge_passes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Merge Passes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_merge_passes%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A37%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_sort_scan{alias=\"$host\"}[$interval]) or irate(mysql_global_status_sort_scan{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Sort Scan", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_sort_scan%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A37%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Sorts", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 9, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_bytes_received{alias=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_received{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_bytes_sent{alias=\"$host\"}[$interval]) or irate(mysql_global_status_bytes_sent{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_bytes_received{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_bytes_received%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "increase(mysql_global_status_bytes_sent{alias=\"$host\"}[1h])", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22-rate(mysql_global_status_bytes_sent%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A34%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "MySQL Network Usage Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 47, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_aborted_connects{alias=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_connects{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Aborted Connects (attempts)", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_aborted_clients{alias=\"$host\"}[$interval]) or irate(mysql_global_status_aborted_clients{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Aborted Clients (timeout)", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22mysql_global_status_max_used_connections%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Aborted Connections", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 48, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_slow_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_slow_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Slow Queries", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_connections%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-6%207%3A44%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Slow Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "General Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 14, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_commands_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{alias=\"$host\"}[5m])>0)", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_commands_total%7Bcommand%3D%5C%22select%5C%22%2C%20alias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A28%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top Command Counters", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 39, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, increase(mysql_global_status_commands_total{alias=\"$host\"}[1h])>0)", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20rate(mysql_global_status_commands_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-10-12%207%3A5%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Top Command Counters Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 8, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_handlers_total{alias=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{alias=\"$host\", handler!~\"commit|rollback|savepoint.*|prepare\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_read_rnd_next%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A0%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "J", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_handlers_total{alias=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[$interval]) or irate(mysql_global_status_handlers_total{alias=\"$host\", handler=~\"commit|rollback|savepoint.*|prepare\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_commit%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A6%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Transaction Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 40, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_info_schema_threads{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_info_schema_threads{alias=\"$host\"}[5m])>0)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20mysql_info_schema_threads%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-10-12%208%3A32%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top Process States", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 49, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, increase(mysql_info_schema_threads{alias=\"$host\"}[1h])>0)", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "{{ state }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22topk(5%2C%20rate(mysql_global_status_commands_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-10-12%207%3A5%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600 - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Top Processes Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Command, Handlers, Processes", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 46, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_qcache_free_memory{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Free Memory", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "F", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_query_cache_size{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Query Cache Size", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Query Cache Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "", - "id": 45, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_hits{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_hits{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Hits", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_inserts{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_inserts{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inserts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_not_cached{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_not_cached{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Not Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_qcache_lowmem_prunes{alias=\"$host\"}[$interval]) or irate(mysql_global_status_qcache_lowmem_prunes{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Prunes", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "F", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_qcache_queries_in_cache{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Queries in Cache", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Query Cache Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Query Cache", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 43, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_opened_files{alias=\"$host\"}[$interval]) or irate(mysql_global_status_opened_files{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Openings", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL File Openings", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 41, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_open_files{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Files", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_open_files_limit{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Files Limit", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Open Files", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 44, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_opened_tables{alias=\"$host\"}[$interval]) or irate(mysql_global_status_opened_tables{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Openings", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_immediate%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Table Openings", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 42, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_status_open_tables{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Open Tables", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "mysql_global_variables_table_open_cache{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Table Open Cache", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_table_locks_waited%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2015%3A45%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Open Tables", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "Files and Tables", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "MySQL Overview | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-summary.json b/dashboards/in-use/mysql-summary.json deleted file mode 100644 index 4184a7090..000000000 --- a/dashboards/in-use/mysql-summary.json +++ /dev/null @@ -1,1089 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "260px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\"}[$interval])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\"}[5m])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ mode }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [ - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "Processes blocked waiting for I/O to complete", - "color": "#E24D42" - }, - { - "alias": "Processes in runnable state", - "color": "#6ED0E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_running{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Processes in runnable state", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_blocked{alias=\"$host\"}", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Processes blocked waiting for I/O to complete", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_blocked%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Processes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_receive_bytes{alias=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_receive_bytes{alias=\"$host\", device!=\"lo\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Inbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_network_transmit_bytes{alias=\"$host\", device!=\"lo\"}[$interval])) or sum(irate(node_network_transmit_bytes{alias=\"$host\", device!=\"lo\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Outbound", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 36, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": true, - "hideZero": true, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 1, - "points": true, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_read_time_ms{device!~\"dm-.+\", alias=\"$host\"}[$interval]) / rate(node_disk_reads_completed{device!~\"dm-.+\", alias=\"$host\"}[$interval])) or (irate(node_disk_read_time_ms{device!~\"dm-.+\", alias=\"$host\"}[5m]) / irate(node_disk_reads_completed{device!~\"dm-.+\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Read: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_read_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_reads_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(rate(node_disk_write_time_ms{device!~\"dm-.+\", alias=\"$host\"}[$interval]) / rate(node_disk_writes_completed{device!~\"dm-.+\", alias=\"$host\"}[$interval])) or (irate(node_disk_write_time_ms{device!~\"dm-.+\", alias=\"$host\"}[5m]) / irate(node_disk_writes_completed{device!~\"dm-.+\", alias=\"$host\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Write: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(node_disk_write_time_ms%7Balias%3D%5C%22%24host%5C%22%7D%5B5m%5D)%20%2F%20rate(node_disk_writes_completed%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%209%3A12%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk Latency", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "ms", - "label": "", - "logBase": 2, - "max": null, - "min": 0, - "show": true - }, - { - "format": "ms", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 35, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_queries{alias=\"$host\"}[$interval]) or irate(mysql_global_status_queries{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Queries", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Queries", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "270px", - "id": 34, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Row Operations", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 32, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_commands_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_commands_total{alias=\"$host\"}[5m])>0)", - "hide": false, - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Com_{{ command }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_commands_total%7Bcommand%3D%5C%22select%5C%22%2C%20alias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-18%2015%3A28%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top MySQL Commands", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 33, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "topk(5, rate(mysql_global_status_handlers_total{alias=\"$host\"}[$interval])>0) or topk(5, irate(mysql_global_status_handlers_total{alias=\"$host\"}[5m])>0)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "{{ handler }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_handler_read_rnd_next%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-20%2016%3A0%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "J", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Top MySQL Handlers", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "MySQL Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Summary Dashboard | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/mysql-trends.json b/dashboards/in-use/mysql-trends.json deleted file mode 100644 index 813708d17..000000000 --- a/dashboards/in-use/mysql-trends.json +++ /dev/null @@ -1,900 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "Prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "height": "", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "hideZero": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval])) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m])) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval] offset 1d)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m] offset 1d)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{alias=\"$host\", mode!=\"idle\"}[$interval] offset 1w)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"}) or sum(irate(node_cpu{alias=\"$host\", mode!=\"idle\"}[5m] offset 1w)) * 100 / count_scalar(node_cpu{mode=\"user\", alias=\"$host\"})", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Busy State 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 37, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval] offset 1d) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m] offset 1d) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{alias=\"$host\"}[$interval] offset 1w) * 1024 or irate(node_vmstat_pgpgin{alias=\"$host\"}[5m] offset 1w) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page In 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Read Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 38, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m]) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval] offset 1d) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m] offset 1d) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{alias=\"$host\"}[$interval] offset 1w) * 1024 or irate(node_vmstat_pgpgout{alias=\"$host\"}[5m] offset 1w) * 1024", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Page Out 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Write Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 35, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval]) or irate(mysql_global_status_questions{alias=\"$host\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval] offset 1d) or irate(mysql_global_status_questions{alias=\"$host\"}[5m] offset 1d)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_questions{alias=\"$host\"}[$interval] offset 1w) or irate(mysql_global_status_questions{alias=\"$host\"}[5m] offset 1w)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Questions 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "MySQL Questions", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 34, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval]) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m])", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval] offset 1d) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m] offset 1d)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }} 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[$interval] offset 1w) or irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation=\"read\"}[5m] offset 1w)", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows {{ operation }} 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Rows Read", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 36, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval])) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m]))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval] offset 1d)) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m] offset 1d))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted 1d ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 300 - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[$interval] offset 1w)) or sum(irate(mysql_global_status_innodb_row_ops_total{alias=\"$host\", operation!=\"read\"}[5m] offset 1w))", - "interval": "$interval", - "intervalFactor": 1, - "legendFormat": "Rows inserted+updated+deleted 1w ago", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22rate(mysql_global_status_innodb_row_ops_total%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D)%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-8-27%2010%3A30%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 300 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "InnoDB Rows Changed", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": true, - "title": "MySQL Stats", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "OS", - "Percona", - "MySQL" - ], - "templating": { - "list": [ - { - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "auto", - "value": "$__auto_interval" - }, - "datasource": "Prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [ - { - "selected": true, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": false, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": "Host", - "multi": false, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(alias)", - "refresh": 1, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "alias", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-12h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "Trends Dashboard | Percona App", - "version": 1 -} \ No newline at end of file diff --git a/dashboards/in-use/nodes.json b/dashboards/in-use/nodes.json deleted file mode 100644 index 4809843ef..000000000 --- a/dashboards/in-use/nodes.json +++ /dev/null @@ -1,911 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "description": "Dashboard to get an overview of one server", - "editable": true, - "gnetId": 22, - "graphTooltip": 0, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 3, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "100 - (avg by (cpu) (irate(node_cpu{mode=\"idle\", instance=\"$server\"}[5m])) * 100)", - "hide": false, - "intervalFactor": 10, - "legendFormat": "{{cpu}}", - "refId": "A", - "step": 50 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Idle CPU", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": "cpu usage", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 9, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "node_load1{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 1m", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "node_load5{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 5m", - "refId": "B", - "step": 20, - "target": "" - }, - { - "expr": "node_load15{instance=\"$server\"}", - "intervalFactor": 4, - "legendFormat": "load 15m", - "refId": "C", - "step": 20, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "System Load", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percentunit", - "logBase": 1, - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 4, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "node_memory_SwapFree{instance=\"172.17.0.1:9100\",job=\"prometheus\"}", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": true, - "steppedLine": false, - "targets": [ - { - "expr": "node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}", - "hide": false, - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory used", - "metric": "", - "refId": "C", - "step": 10 - }, - { - "expr": "node_memory_Buffers{instance=\"$server\"}", - "interval": "", - "intervalFactor": 2, - "legendFormat": "memory buffers", - "metric": "", - "refId": "E", - "step": 10 - }, - { - "expr": "node_memory_Cached{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory cached", - "metric": "", - "refId": "F", - "step": 10 - }, - { - "expr": "node_memory_MemFree{instance=\"$server\"}", - "intervalFactor": 2, - "legendFormat": "memory free", - "metric": "", - "refId": "D", - "step": 10 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "min": "0", - "show": true - }, - { - "format": "short", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 5, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "((node_memory_MemTotal{instance=\"$server\"} - node_memory_MemFree{instance=\"$server\"} - node_memory_Buffers{instance=\"$server\"} - node_memory_Cached{instance=\"$server\"}) / node_memory_MemTotal{instance=\"$server\"}) * 100", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "80, 90", - "title": "Memory Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "avg" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 6, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "read", - "yaxis": 1 - }, - { - "alias": "{instance=\"172.17.0.1:9100\"}", - "yaxis": 2 - }, - { - "alias": "io time", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 9, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (instance) (rate(node_disk_bytes_read{instance=\"$server\"}[2m]))", - "hide": false, - "intervalFactor": 4, - "legendFormat": "read", - "refId": "A", - "step": 20, - "target": "" - }, - { - "expr": "sum by (instance) (rate(node_disk_bytes_written{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "written", - "refId": "B", - "step": 20 - }, - { - "expr": "sum by (instance) (rate(node_disk_io_time_ms{instance=\"$server\"}[2m]))", - "intervalFactor": 4, - "legendFormat": "io time", - "refId": "C", - "step": 20 - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Disk I/O", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "ms", - "logBase": 1, - "show": true - } - ] - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": true, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "hideTimeOverride": false, - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [ - { - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [ - { - "from": "null", - "text": "N/A", - "to": "null" - } - ], - "span": 3, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [ - { - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=\"$server\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=\"$server\"})", - "intervalFactor": 2, - "refId": "A", - "step": 60, - "target": "" - } - ], - "thresholds": "0.75, 0.9", - "title": "Disk Space Usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [ - { - "op": "=", - "text": "N/A", - "value": "null" - } - ], - "valueName": "current" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 8, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_receive_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "A", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Received", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "fill": 1, - "grid": { - "threshold1Color": "rgba(216, 200, 27, 0.27)", - "threshold2Color": "rgba(234, 112, 112, 0.22)" - }, - "id": 10, - "isNew": false, - "legend": { - "alignAsTable": false, - "avg": false, - "current": false, - "hideEmpty": false, - "hideZero": false, - "max": false, - "min": false, - "rightSide": false, - "show": true, - "total": false, - "values": false - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "connected", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [ - { - "alias": "transmitted", - "yaxis": 2 - } - ], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "rate(node_network_transmit_bytes{instance=\"$server\",device!~\"lo\"}[5m])", - "hide": false, - "intervalFactor": 2, - "legendFormat": "{{device}}", - "refId": "B", - "step": 10, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Transmitted", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "cumulative" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "bytes", - "logBase": 1, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "system" - ], - "templating": { - "list": [ - { - "allValue": null, - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": false, - "label": null, - "multi": false, - "name": "server", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 1, - "regex": "", - "sort": 0, - "tagValuesQuery": "", - "tags": [], - "tagsQuery": "", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "browser", - "title": "Nodes", - "version": 3 -} \ No newline at end of file diff --git a/dashboards/in-use/system.json b/dashboards/in-use/system.json deleted file mode 100644 index 62c708540..000000000 --- a/dashboards/in-use/system.json +++ /dev/null @@ -1,1953 +0,0 @@ -{ - "__inputs": [{ - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - }], - "__requires": [{ - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.2" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "singlestat", - "name": "Singlestat", - "version": "" - } - ], - "annotations": { - "list": [{ - "builtIn": 1, - "datasource": "-- Grafana --", - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - }, - { - "datasource": "${DS_PROMETHEUS}", - "enable": false, - "expr": "ALERTS{instance=~\"^$host$\", alertstate=\"firing\"}", - "iconColor": "rgb(252, 5, 0)", - "name": "Alert", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{alertstate}}", - "titleFormat": "{{ alertname }}" - }, - { - "datasource": "${DS_PROMETHEUS}", - "enable": true, - "expr": "ALERTS{instance=~\"^$host$\",alertstate=\"pending\"}", - "iconColor": "rgb(228, 242, 9)", - "name": "Warning", - "tagKeys": "severity", - "textFormat": "{{ alias }} : {{ alertstate }}", - "titleFormat": "{{ alertname }}" - } - ] - }, - "description": "Prometheus for system metrics. \r\nLoad, CPU, RAM, network, process ... (mod of https://grafana.com/dashboards/159)", - "editable": true, - "gnetId": 159, - "graphTooltip": 1, - "hideControls": false, - "id": null, - "links": [], - "refresh": "30s", - "rows": [{ - "collapse": false, - "height": "250px", - "panels": [{ - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 1, - "editable": true, - "error": false, - "format": "s", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 19, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "s", - "postfixFontSize": "80%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 4, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_time{instance=~\"^$host$\"} - node_boot_time{instance=~\"^$host$\"}", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_time%7Balias%3D%5C%22%24host%5C%22%7D%20-%20node_boot_time%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A25%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "300,3600", - "title": "System Uptime", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "editable": true, - "error": false, - "format": "none", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 25, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "count(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300 - }], - "thresholds": "", - "title": "Virtual CPUs", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": false, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "format": "bytes", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "55px", - "id": 26, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": false, - "lineColor": "rgb(31, 120, 193)", - "show": false - }, - "tableColumn": "", - "targets": [{ - "expr": "sum(node_memory_MemAvailable{instance=~\"^$host$\"})", - "interval": "", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_memory_MemAvailable", - "refId": "A", - "step": 30 - }], - "thresholds": "", - "title": "RAM available", - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "editable": true, - "error": false, - "format": "percent", - "gauge": { - "maxValue": 100, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 9, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "80%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "calculatedInterval": "10m", - "datasourceErrors": {}, - "errors": {}, - "expr": "(sum(node_memory_MemAvailable{instance=~\"^$host$\"}) or (sum(node_memory_MemFree{instance=~\"^$host$\"}) + sum(node_memory_Buffers{instance=~\"^$host$\"}) + sum(node_memory_Cached{instance=~\"^$host$\"}))) / sum(node_memory_MemTotal{instance=~\"^$host$\"}) * 100", - "interval": "5m", - "intervalFactor": 1, - "legendFormat": "", - "metric": "node_mem", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%20%2F%20node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20*%20100%22%2C%22range_input%22%3A%2243201s%22%2C%22end_input%22%3A%222015-9-15%2013%3A54%22%2C%22step_input%22%3A%22%22%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 300 - }], - "thresholds": "90,95", - "title": "Memory Available", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [], - "valueName": "current" - }, - { - "cacheTimeout": null, - "colorBackground": false, - "colorValue": true, - "colors": [ - "rgba(50, 172, 45, 0.97)", - "rgba(237, 129, 40, 0.89)", - "rgba(245, 54, 54, 0.9)" - ], - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "editable": true, - "error": false, - "format": "percentunit", - "gauge": { - "maxValue": 1, - "minValue": 0, - "show": false, - "thresholdLabels": false, - "thresholdMarkers": true - }, - "height": "50px", - "id": 7, - "interval": null, - "links": [], - "mappingType": 1, - "mappingTypes": [{ - "name": "value to text", - "value": 1 - }, - { - "name": "range to text", - "value": 2 - } - ], - "maxDataPoints": 100, - "nullPointMode": "connected", - "nullText": null, - "postfix": "", - "postfixFontSize": "50%", - "prefix": "", - "prefixFontSize": "50%", - "rangeMaps": [{ - "from": "null", - "text": "N/A", - "to": "null" - }], - "span": 2, - "sparkline": { - "fillColor": "rgba(31, 118, 189, 0.18)", - "full": true, - "lineColor": "rgb(31, 120, 193)", - "show": true - }, - "tableColumn": "", - "targets": [{ - "expr": "(sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"}) - sum(node_filesystem_free{device!=\"rootfs\",instance=~\"^$host$\"})) / sum(node_filesystem_size{device!=\"rootfs\",instance=~\"^$host$\"})", - "format": "time_series", - "interval": "5m", - "intervalFactor": 1, - "refId": "A", - "step": 300, - "target": "" - }], - "thresholds": "75,95", - "title": "Disk space usage", - "transparent": false, - "type": "singlestat", - "valueFontSize": "80%", - "valueMaps": [{ - "op": "=", - "text": "N/A", - "value": "null" - }], - "valueName": "current" - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "260px", - "id": 2, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(rate(node_cpu{instance=~\"^$host$\"}[$interval])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"}) or sum(irate(node_cpu{instance=~\"^$host$\"}[5m])) by (mode) * 100 / count_scalar(node_cpu{mode=\"user\", instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "{{ mode }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22sum(rate(node_cpu%7Balias%3D%5C%22%24host%5C%22%7D%5B%24interval%5D))%20by%20(mode)%20*%20100%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2 - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "CPU Usage", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "percent", - "label": "", - "logBase": 1, - "max": 100, - "min": 0, - "show": true - }, - { - "format": "short", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 18, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "sortDesc": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Load 1m", - "color": "#E24D42" - }, - { - "alias": "Load 5m", - "color": "#E0752D" - }, - { - "alias": "Load 15m", - "color": "#E5AC0E" - } - ], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load1{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 1m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load1%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223601s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load5{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 5m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load5%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 2, - "target": "" - }, - { - "calculatedInterval": "10s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_load15{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Load 15m", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_load15%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%223600s%22%2C%22end_input%22%3A%222015-10-22%2015%3A27%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Afalse%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 2, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Load Average", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "System Stats", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "300px", - "panels": [{ - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 6, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#0A437C" - }, - { - "alias": "Available", - "color": "#5195CE" - }, - { - "alias": "Total", - "color": "#052B51", - "legend": false, - "stack": false - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Total", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "C", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"}))", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemAvailable{instance=~\"^$host$\"} or (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Available", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "height": "", - "id": 29, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemTotal{instance=~\"^$host$\"} - (node_memory_MemFree{instance=~\"^$host$\"} + node_memory_Buffers{instance=~\"^$host$\"} + node_memory_Cached{instance=~\"^$host$\"})", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_MemFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Buffers{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Buffers", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "D", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_Cached{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Cached", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "E", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Memory Distribution", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 24, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Forks", - "color": "#EF843C" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_forks{instance=~\"^$host$\"}[$interval]) or irate(node_forks{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Forks", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Forks", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 20, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Processes blocked waiting for I/O to complete", - "color": "#E24D42" - }, - { - "alias": "Processes in runnable state", - "color": "#6ED0E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_running{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes in runnable state", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_procs_blocked{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Processes blocked waiting for I/O to complete", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_blocked%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Processes", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 27, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_context_switches{instance=~\"^$host$\"}[$interval]) or irate(node_context_switches{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Context Switches", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Context Switches", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 28, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Interrupts", - "color": "#D683CE" - }], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2m", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_intr{instance=~\"^$host$\"}[$interval]) or irate(node_intr{instance=~\"^$host$\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Interrupts", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_procs_running%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%2243200s%22%2C%22end_input%22%3A%222015-9-18%2013%3A46%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Interrupts", - "tooltip": { - "msResolution": true, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "none", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "none", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 21, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Inbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[$interval]) or irate(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[5m])", - "intervalFactor": 1, - "legendFormat": "Outbound: {{ device }}", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Network Traffic", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": true, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 22, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "sort": "min", - "sortDesc": true, - "total": false, - "values": true - }, - "lines": false, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_receive_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Received", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 3600, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "sum(increase(node_network_transmit_bytes{instance=~\"^$host$\", device!=\"lo\"}[1h]))", - "interval": "1h", - "intervalFactor": 1, - "legendFormat": "Sent", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 3600, - "target": "" - } - ], - "thresholds": [], - "timeFrom": "24h", - "timeShift": null, - "title": "Network Utilization Hourly", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 6, - "grid": {}, - "id": 23, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [{ - "alias": "Used", - "color": "#584477" - }, - { - "alias": "Free", - "color": "#AEA2E0" - } - ], - "spaceLength": 10, - "span": 6, - "stack": true, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapTotal{instance=~\"^$host$\"} - node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Used", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "node_memory_SwapFree{instance=~\"^$host$\"}", - "intervalFactor": 1, - "legendFormat": "Free", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "bytes", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 30, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpin{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpin{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pswpout{instance=~\"^$host$\"}[$interval]) * 4096 or irate(node_vmstat_pswpout{instance=~\"^$host$\"}[5m]) * 4096", - "intervalFactor": 1, - "legendFormat": "Swap Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "Swap Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - }, - { - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 2, - "editable": true, - "error": false, - "fill": 2, - "grid": {}, - "id": 31, - "legend": { - "alignAsTable": true, - "avg": true, - "current": false, - "hideEmpty": false, - "max": true, - "min": true, - "rightSide": false, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 2, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 6, - "stack": false, - "steppedLine": false, - "targets": [{ - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgin{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgin{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page In", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemTotal%7Balias%3D%5C%22%24host%5C%22%7D%20-%20(node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D)%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "A", - "step": 5, - "target": "" - }, - { - "calculatedInterval": "2s", - "datasourceErrors": {}, - "errors": {}, - "expr": "rate(node_vmstat_pgpgout{instance=~\"^$host$\"}[$interval]) * 1024 or irate(node_vmstat_pgpgout{instance=~\"^$host$\"}[5m]) * 1024", - "intervalFactor": 1, - "legendFormat": "Page Out", - "metric": "", - "prometheusLink": "/api/datasources/proxy/1/graph#%5B%7B%22expr%22%3A%22node_memory_MemFree%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Buffers%7Balias%3D%5C%22%24host%5C%22%7D%20%2B%20node_memory_Cached%7Balias%3D%5C%22%24host%5C%22%7D%22%2C%22range_input%22%3A%22900s%22%2C%22end_input%22%3A%222015-10-22%2015%3A25%22%2C%22step_input%22%3A%22%22%2C%22stacked%22%3Atrue%2C%22tab%22%3A0%7D%5D", - "refId": "B", - "step": 5, - "target": "" - } - ], - "thresholds": [], - "timeFrom": null, - "timeShift": null, - "title": "I/O Activity", - "tooltip": { - "msResolution": false, - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [{ - "format": "Bps", - "label": "", - "logBase": 1, - "max": null, - "min": 0, - "show": true - }, - { - "format": "bytes", - "logBase": 1, - "max": null, - "min": 0, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "New row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [ - "system" - ], - "templating": { - "list": [{ - "allFormat": "glob", - "auto": true, - "auto_count": 200, - "auto_min": "1s", - "current": { - "text": "5s", - "value": "5s" - }, - "datasource": "prometheus", - "hide": 0, - "includeAll": false, - "label": "Interval", - "multi": false, - "multiFormat": "glob", - "name": "interval", - "options": [{ - "selected": false, - "text": "auto", - "value": "$__auto_interval" - }, - { - "selected": false, - "text": "1s", - "value": "1s" - }, - { - "selected": true, - "text": "5s", - "value": "5s" - }, - { - "selected": false, - "text": "1m", - "value": "1m" - }, - { - "selected": false, - "text": "5m", - "value": "5m" - }, - { - "selected": false, - "text": "1h", - "value": "1h" - }, - { - "selected": false, - "text": "6h", - "value": "6h" - }, - { - "selected": false, - "text": "1d", - "value": "1d" - } - ], - "query": "1s,5s,1m,5m,1h,6h,1d", - "refresh": 2, - "type": "interval" - }, - { - "allFormat": "glob", - "allValue": ".+", - "current": {}, - "datasource": "${DS_PROMETHEUS}", - "hide": 0, - "includeAll": true, - "label": "Host", - "multi": true, - "multiFormat": "regex values", - "name": "host", - "options": [], - "query": "label_values(node_boot_time, instance)", - "refresh": 2, - "refresh_on_load": false, - "regex": "", - "sort": 0, - "tagValuesQuery": "instance", - "tags": [], - "tagsQuery": "up", - "type": "query", - "useTags": false - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "collapse": false, - "enable": true, - "notice": false, - "now": true, - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "status": "Stable", - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ], - "type": "timepicker" - }, - "timezone": "browser", - "title": "System", - "version": 0 -} \ No newline at end of file diff --git a/dashboards/temp/Alerts Copy-1516600505131.json b/dashboards/temp/Alerts Copy-1516600505131.json deleted file mode 100644 index fbab1a8df..000000000 --- a/dashboards/temp/Alerts Copy-1516600505131.json +++ /dev/null @@ -1,782 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "panel", - "id": "alertlist", - "name": "Alert List", - "version": "" - }, - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.3" - }, - { - "type": "panel", - "id": "graph", - "name": "Graph", - "version": "" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "refresh": false, - "rows": [ - { - "collapse": false, - "height": 250, - "panels": [ - { - "id": 2, - "limit": 10, - "links": [], - "onlyAlertsOnDashboard": false, - "show": "current", - "sortOrder": 1, - "span": 12, - "stateFilter": [], - "title": "Current Alerts", - "type": "alertlist" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 223, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 70 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "@channel The memory used within the Kubernetes cluster is above the defined threshold.", - "name": "Cluster Memory Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": 0, - "description": "Percentage of memory used across the cluster.", - "fill": 1, - "id": 1, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(sum(node_memory_MemTotal) - sum(node_memory_MemAvailable)) / sum(node_memory_MemTotal) * 100", - "format": "time_series", - "interval": "", - "intervalFactor": 1, - "legendFormat": "memory used", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 70 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Cluster Memory Used", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "transparent": false, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 70 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "@channel The memory used on the following node(s) is above the defined threshold.", - "name": "Node Memory Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 3, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "(node_memory_MemTotal - node_memory_MemAvailable) / node_memory_MemTotal * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{instance}}", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 70 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Node Memory Used", - "tooltip": { - "shared": false, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 70 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "@channel The CPU load across the Kubernetes cluster is above the defined threshold.", - "name": "Cluster CPU Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "decimals": null, - "fill": 1, - "id": 4, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": true, - "min": true, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum(rate(node_cpu{mode!=\"idle\"}[5m])) / count(node_cpu{mode=\"idle\"}) * 100", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "cpu used", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 70 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Cluster CPU Used", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 70 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "@channel The CPU load on the following node(s) is above the defined threshold.", - "name": "Node CPU Used alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 5, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (instance) (rate(node_cpu{mode!=\"idle\"}[5m])) / count by (instance) (node_cpu{mode=\"idle\"}) * 100", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ instance }}", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 70 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "Node CPU Used", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": 250, - "panels": [ - { - "alert": { - "conditions": [ - { - "evaluator": { - "params": [ - 20 - ], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": [ - "A", - "5m", - "now" - ] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "frequency": "60s", - "handler": 1, - "message": "@channel The IO wait on the following node(s) is above the defined threshold.", - "name": "IO Wait alert", - "noDataState": "no_data", - "notifications": [] - }, - "aliasColors": {}, - "bars": false, - "dashLength": 10, - "dashes": false, - "datasource": "${DS_PROMETHEUS}", - "fill": 1, - "id": 6, - "legend": { - "alignAsTable": true, - "avg": false, - "current": true, - "max": false, - "min": false, - "rightSide": true, - "show": true, - "total": false, - "values": true - }, - "lines": true, - "linewidth": 1, - "links": [], - "nullPointMode": "null", - "percentage": false, - "pointradius": 5, - "points": false, - "renderer": "flot", - "seriesOverrides": [], - "spaceLength": 10, - "span": 12, - "stack": false, - "steppedLine": false, - "targets": [ - { - "expr": "sum by (instance) (rate(node_cpu{mode=\"iowait\"}[5m]))", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "{{ instance }}", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "fill": true, - "line": true, - "op": "gt", - "value": 20 - } - ], - "timeFrom": null, - "timeShift": null, - "title": "IO Wait", - "tooltip": { - "shared": true, - "sort": 0, - "value_type": "individual" - }, - "type": "graph", - "xaxis": { - "buckets": null, - "mode": "time", - "name": null, - "show": true, - "values": [] - }, - "yaxes": [ - { - "format": "percent", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": true - }, - { - "format": "short", - "label": null, - "logBase": 1, - "max": null, - "min": null, - "show": false - } - ] - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Alerts Copy", - "version": 25 -} \ No newline at end of file diff --git a/dashboards/temp/Cluster - Pods-1516597155979.json b/dashboards/temp/Cluster - Pods-1516597155979.json deleted file mode 100644 index 260631c83..000000000 --- a/dashboards/temp/Cluster - Pods-1516597155979.json +++ /dev/null @@ -1,303 +0,0 @@ -{ - "__inputs": [ - { - "name": "DS_PROMETHEUS", - "label": "prometheus", - "description": "", - "type": "datasource", - "pluginId": "prometheus", - "pluginName": "Prometheus" - } - ], - "__requires": [ - { - "type": "grafana", - "id": "grafana", - "name": "Grafana", - "version": "4.6.3" - }, - { - "type": "datasource", - "id": "prometheus", - "name": "Prometheus", - "version": "1.0.0" - }, - { - "type": "panel", - "id": "table", - "name": "Table", - "version": "" - } - ], - "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, - "hideControls": false, - "id": null, - "links": [], - "rows": [ - { - "collapse": false, - "height": 250, - "panels": [ - { - "columns": [], - "datasource": "${DS_PROMETHEUS}", - "fontSize": "100%", - "id": 2, - "links": [], - "pageSize": 30, - "scroll": false, - "showHeader": true, - "sort": { - "col": 3, - "desc": true - }, - "span": 12, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "namespace", - "thresholds": [], - "type": "number", - "unit": "short" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "pod_name", - "thresholds": [], - "type": "number", - "unit": "short" - }, - { - "alias": "Memory", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "Value", - "thresholds": [], - "type": "number", - "unit": "decbytes" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 2, - "pattern": "/.*/", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum by (namespace,pod_name) (container_memory_usage_bytes{pod_name!~\"cronjob.*\",job!=\"kubernetes-apiservers\",pod_name!=\"\"})", - "format": "table", - "instant": true, - "intervalFactor": 1, - "refId": "A" - } - ], - "title": "Pod - Current Memory Use", - "transform": "table", - "type": "table" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - }, - { - "collapse": false, - "height": "250px", - "panels": [ - { - "columns": [], - "datasource": "${DS_PROMETHEUS}", - "fontSize": "100%", - "id": 1, - "links": [], - "pageSize": 30, - "scroll": false, - "showHeader": true, - "sort": { - "col": 3, - "desc": true - }, - "span": 12, - "styles": [ - { - "alias": "Time", - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "pattern": "Time", - "type": "hidden" - }, - { - "alias": "CPU (seconds)", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 6, - "pattern": "Value", - "thresholds": [], - "type": "number", - "unit": "short" - }, - { - "alias": "Namespace", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "namespace", - "thresholds": [], - "type": "number", - "unit": "short" - }, - { - "alias": "Pod", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "dateFormat": "YYYY-MM-DD HH:mm:ss", - "decimals": 2, - "pattern": "pod_name", - "thresholds": [], - "type": "number", - "unit": "short" - }, - { - "alias": "", - "colorMode": null, - "colors": [ - "rgba(245, 54, 54, 0.9)", - "rgba(237, 129, 40, 0.89)", - "rgba(50, 172, 45, 0.97)" - ], - "decimals": 2, - "pattern": "/.*/", - "thresholds": [], - "type": "number", - "unit": "short" - } - ], - "targets": [ - { - "expr": "sum by (namespace,pod_name) (rate(container_cpu_usage_seconds_total{pod_name!~\"cronjob.*\",job!=\"kubernetes-apiservers\",pod_name!=\"\"}[5m]))", - "format": "table", - "instant": true, - "intervalFactor": 1, - "refId": "A" - } - ], - "title": "Pod - Current CPU Usage", - "transform": "table", - "type": "table" - } - ], - "repeat": null, - "repeatIteration": null, - "repeatRowId": null, - "showTitle": false, - "title": "Dashboard Row", - "titleSize": "h6" - } - ], - "schemaVersion": 14, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - }, - "timezone": "", - "title": "Cluster - Pods", - "version": 3 -} \ No newline at end of file diff --git a/docker-compose.end2end.yaml b/docker-compose.end2end.yaml deleted file mode 100644 index c2abb6411..000000000 --- a/docker-compose.end2end.yaml +++ /dev/null @@ -1,19 +0,0 @@ -version: '3.2' -services: - tests: - environment: - - WEBHOOK_HOST=webhook-handler-lagoon-master.lagoon.ch.amazee.io - - WEBHOOK_PORT=443 - - WEBHOOK_PROTOCOL=https - - OPENSHIFT_ROUTE_SUFFIX=ch.amazee.io - - REST2TASKS_HOST=rest2tasks-lagoon-master.lagoon.ch.amazee.io - - REST2TASKS_PORT=443 - - REST2TASKS_PROTOCOL=https - - WEBHOOK_REPO_PREFIX=git@github.com:lagoon-end2end-ci/ - - GIT_REPO_PREFIX=git@github.com:lagoon-end2end-ci/ - - SSH_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY----- - - SSH_HOST=api-lagoon-master.lagoon.ch.amazee.io - - SSH_PORT=31472 - - API_HOST=api-lagoon-master.lagoon.ch.amazee.io - - API_PROTOCOL=https - - API_PORT=443 \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index 4dc4bd247..000000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,393 +0,0 @@ -version: '3.2' -services: - api-db: - image: ${IMAGE_REPO:-lagoon}/api-db - volumes: - - ./services/api-db/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d - - ./services/api-db/rerun_initdb.sh:/rerun_initdb.sh - ports: - - '3306:3306' - labels: - lagoon.type: mariadb - lagoon.image: amazeeiolagoon/api-db:v0-22-0 - cli: - image: ${IMAGE_REPO:-lagoon}/cli - volumes: - - ./cli/src:/app/cli/src:delegated - - ./node-packages:/app/node-packages:delegated - environment: - - SSH_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY----- - - SSH_HOST=ssh - - SSH_PORT=2020 - - API_HOST=api - - API_PROTOCOL=http - - API_PORT=3000 - labels: - lagoon.type: none - depends_on: - - ssh - webhook-handler: - image: ${IMAGE_REPO:-lagoon}/webhook-handler - command: yarn run dev - ports: - - '7777:3000' - volumes: - - ./services/webhook-handler/src:/app/services/webhook-handler/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/webhook-handler/.lagoon.app.yml - lagoon.image: amazeeiolagoon/webhook-handler:v0-22-0 - broker: - image: ${IMAGE_REPO:-lagoon}/broker-single - ports: - - '15672:15672' - - '5672:5672' - labels: - lagoon.type: rabbitmq-cluster - lagoon.template: services/broker/.lagoon.app.yml - lagoon.image: amazeeiolagoon/broker:v0-22-0 - openshiftremove: - image: ${IMAGE_REPO:-lagoon}/openshiftremove - command: yarn run dev - volumes: - - ./services/openshiftremove/src:/app/services/openshiftremove/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/openshiftremove/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftremove:v0-22-0 - openshiftbuilddeploy: - image: ${IMAGE_REPO:-lagoon}/openshiftbuilddeploy - command: yarn run dev - environment: - - CI=${CI:-true} - volumes: - - ./services/openshiftbuilddeploy/src:/app/services/openshiftbuilddeploy/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/openshiftbuilddeploy/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftbuilddeploy:v0-22-0 - openshiftbuilddeploymonitor: - image: ${IMAGE_REPO:-lagoon}/openshiftbuilddeploymonitor - command: yarn run dev - volumes: - - ./services/openshiftbuilddeploymonitor/src:/app/services/openshiftbuilddeploymonitor/src - - ./node-packages:/app/node-packages:delegated - environment: - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-XXXXXXXXXXXXXXXXXXXX} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-xxxxxxxxxxxxxxxxxxxx} - - AWS_BUCKET=${AWS_BUCKET:-aws-bucket} - labels: - lagoon.type: custom - lagoon.template: services/openshiftbuilddeploymonitor/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftbuilddeploymonitor:v0-22-0 - openshiftjobs: - image: ${IMAGE_REPO:-lagoon}/openshiftjobs - command: yarn run dev - volumes: - - ./services/openshiftjobs/src:/app/services/openshiftjobs/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/openshiftjobs/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftjobs:v0-22-0 - openshiftjobsmonitor: - image: ${IMAGE_REPO:-lagoon}/openshiftjobsmonitor - command: yarn run dev - volumes: - - ./services/openshiftjobsmonitor/src:/app/services/openshiftjobsmonitor/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/openshiftjobsmonitor/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftjobsmonitor:v0-22-0 - openshiftmisc: - image: ${IMAGE_REPO:-lagoon}/openshiftmisc - command: yarn run dev - volumes: - - ./services/openshiftmisc/src:/app/services/openshiftmisc/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/openshiftmisc/.lagoon.app.yml - lagoon.image: amazeeiolagoon/openshiftmisc:v0-22-0 - logs2rocketchat: - image: ${IMAGE_REPO:-lagoon}/logs2rocketchat - command: yarn run dev - volumes: - - ./services/logs2rocketchat/src:/app/services/logs2rocketchat/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/logs2rocketchat/.lagoon.app.yml - lagoon.image: amazeeiolagoon/logs2rocketchat:v0-22-0 - logs2slack: - image: ${IMAGE_REPO:-lagoon}/logs2slack - command: yarn run dev - volumes: - - ./services/logs2slack/src:/app/services/logs2slack/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/logs2slack/.lagoon.app.yml - lagoon.image: amazeeiolagoon/logs2slack:v0-22-0 - webhooks2tasks: - image: ${IMAGE_REPO:-lagoon}/webhooks2tasks - command: yarn run dev - volumes: - - ./services/webhooks2tasks/src:/app/services/webhooks2tasks/src - - ./node-packages:/app/node-packages:delegated - labels: - lagoon.type: custom - lagoon.template: services/webhooks2tasks/.lagoon.app.yml - lagoon.image: amazeeiolagoon/webhooks2tasks:v0-22-0 - rest2tasks: - image: ${IMAGE_REPO:-lagoon}/rest2tasks - command: yarn run dev - volumes: - - ./services/rest2tasks/src:/app/services/rest2tasks/src - - ./node-packages:/app/node-packages:delegated - ports: - - '5555:3000' - labels: - lagoon.type: custom - lagoon.template: services/rest2tasks/.lagoon.app.yml - lagoon.image: amazeeiolagoon/rest2tasks:v0-22-0 - api: - image: ${IMAGE_REPO:-lagoon}/api - command: yarn run dev - volumes: - - ./services/api/src:/app/services/api/src - - ./node-packages:/app/node-packages:delegated - depends_on: - - api-db - - local-api-data-watcher-pusher - - keycloak - ports: - - '3000:3000' - labels: - lagoon.type: custom - lagoon.template: services/api/.lagoon.app.yml - lagoon.image: amazeeiolagoon/api:v0-22-0 - ui: - image: ${IMAGE_REPO:-lagoon}/ui - command: yarn run dev - volumes: - - ./services/ui/src:/app/services/ui/src - - ./services/ui/.env.defaults:/app/services/ui/.env.defaults - - ./services/ui/.env.schema:/app/services/ui/.env.schema - - ./services/ui/package.json:/app/services/ui/package.json - ports: - - '8888:3003' - labels: - lagoon.type: custom - lagoon.template: services/ui/.lagoon.app.yml - lagoon.image: amazeeiolagoon/ui:v0-22-0 - ssh: - image: ${IMAGE_REPO:-lagoon}/ssh - depends_on: - - api - - auth-server - ports: - - '2020:2020' - # command: - # - "/usr/sbin/sshd" - # - "-e" - # - "-ddd" - # - "-f" - # - "/etc/ssh/sshd_config" - environment: - - OPENSHIFT_CONSOLE_URL=https://192.168.99.100:8443 - user: '111111111' - volumes: - - ./services/ssh/home/command.sh:/home/command.sh - - ./services/ssh/home/rsh.sh:/home/rsh.sh - labels: - lagoon.type: custom - lagoon.template: services/ssh/.lagoon.app.yml - lagoon.image: amazeeiolagoon/ssh:v0-22-0 - auth-server: - image: ${IMAGE_REPO:-lagoon}/auth-server - command: yarn run dev - environment: - - JWTISSUER=auth-server.dev - - JWTAUDIENCE=api.dev - volumes: - - ./services/auth-server/src:/app/services/auth-server/src - user: '111111111' - ports: - - '3001:3000' - labels: - lagoon.type: custom - lagoon.template: services/auth-server/.lagoon.app.yml - lagoon.image: amazeeiolagoon/auth-server:v0-22-0 - keycloak: - image: ${IMAGE_REPO:-lagoon}/keycloak - user: '111111111' - depends_on: - - keycloak-db - ports: - - '8088:8080' - labels: - lagoon.type: custom - lagoon.template: services/keycloak/.lagoon.app.yml - lagoon.image: amazeeiolagoon/keycloak:v0-22-0 - keycloak-db: - image: ${IMAGE_REPO:-lagoon}/keycloak-db - ports: - - '3336:3306' - labels: - lagoon.type: mariadb - lagoon.image: amazeeiolagoon/keycloak-db:v0-22-0 - tests: - image: ${IMAGE_REPO:-lagoon}/tests - environment: - - WEBHOOK_HOST=webhook-handler - - WEBHOOK_PORT=3000 - - WEBHOOK_PROTOCOL=http - - REST2TASKS_HOST=rest2tasks - - REST2TASKS_PORT=3000 - - REST2TASKS_PROTOCOL=http - - OPENSHIFT_ROUTE_SUFFIX=192.168.99.100.xip.io - - WEBHOOK_REPO_PREFIX=ssh://git@192.168.99.1:2222/git/ - - GIT_REPO_PREFIX=git@local-git:/git/ - - SSH_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAxGZZrOV7Islo5p51Moabfd1YB8qbHvQZfJDZJmSU4jNxMf8G\nQH8KIM6ndi60xIiDlkh9R50Gs0fgnPaBwpjMjcUay5EvzBJdMmd/EPhg359+4f5Z\nQiGTVaB5UoGJKg9DEK4Xxi+QLpQ1CiJXvd3QOqnQlJZ2WYwz4kdLxF0d+sRrl+0G\nAISt9Gg9kq6wa7k7RRr4/OyD/9DhDr1GXvHXFPRv6QqKq084CqiUaarP7OcbZKi5\nEyMkf0s86ZTttQPqQijWsenLAw6t7J0vM38eojPDMFX4fJ7wVvbHmsdcwb2YxwD0\nk7I85mV5uM99v7owJ/0YSJGcN2YESq8c68rbRp1iSfDhchd9SUyYMFlrj3R+dxte\nTwvN2W5hIEld8Ip+dUWUVaaTeLkFLmqmVhvcMJNmuj+Wnp9USwki6U5HdpgBJPT5\nYJia3/LyE5IlPaRfZ+vBDQqKOeeqkncVtqcZ468ylT0qpqjtV4OSuCzl+P/TeJ+K\npCxDoqp88yQpYRYn9ztvEVvOkT8RERnT0/NVCNKAwHFOXrkK/BJs/h3fj2NddeVC\nJXdwiB4m+T2C/RHtGxVColqUf2nEntXxweuJgqBz+4YxXqRrKu4p5L4NuudcFAyg\nbIRpbaTZDI+vmmXnTXNP6ymMo5fNJ0/IPEBAoDkkc6ZmKdM5Yth6RaCzolsCAwEA\nAQKCAgBRL4n0SaxcFevyISCLMU+HeP8RwXPcGMWMU4ggMcXFt8QcCbK46Ir0QtjA\nps/8yf2zGuYGu2dwps63s8KyAV3VYNwRuEOM1S6HTncdOb850YGuw+h7yMtRwxND\nwt5Db6mmdIDJYRH13zgJp2ajytRv25CoS4ZCwA0WhahRVLi214kudUFc53vNI2YI\ng4PUE+7nQx4X12E9V0ghQqabStdBB0ZXjA8Ef6vH5CXthDmNUX9mXcSbn5RPtndI\ni1Kz2Bl3HdCaHO3ZprDItbU0UWEFZeZSzcb5JO5u1HZwiebTA5/q638uqqg4CUyG\n0+bEYZ/Ud/AY13A/CkHN6ZNH+UQotCH3GLyaTQq6OhyXlgMBojn3xs9iMUclFcuy\nkbZ1jAxqci25pxCIeNDHBDKRyxgSkDPna8ZZ4eKGXjIZzsds4+IDkYJLMg0OCtd2\nKm+ZPM2CFU2YCqt11dlr0higGK/9gdpajJMVgEYAmigQ670LdcBc4XIOpPMrR70a\nPjbF9ze/UqtKDWtz8KMIUcvr0CjhHa3XRgMJiM34hIOZU6xf6rjEgkN2Geq24u1b\nhUW8URb+5dcasQ9iIfkNn3R+zK5PzyvQNf6+XrbVjpLqPHXJYrD85EKlXkPqiE6y\n3ehYMrIaZIY6gMuIVcg8AEtsm5EwQY7ETw4YnMQLKfyweLsHEQKCAQEA5vavDyQj\nn6PqfF1Ntr3N/FfwRr/167HB+/3wHT+FwRpCw62ACeBC0iFXmzG2wfQfot60fUGa\nQEJiUDGZFvBM0tiTpzmgGG7QpRbPe1919Sl5LZeLA9bngRnmqn5zAkmVTeBCO/4F\nMSk9hnBZ0v0W3DqNmjuIH298g3gl4VJeKpILd62LbhjvhjT/LXlekYDEj3p9Xob8\n1OQxFJgftFyg4P07RRaUzsNLhqEdY3VxDcUMb9459fEYeb7sYig+zVPaZQ31aMVK\nj6K+XiH5M5uKJWkPdMDUG84jreFAdBY9kGCuSulTWgmTLlMKSI85q5hkckY2EQQL\n5u456xfyuFcnEwKCAQEA2bCCcqcGIAiMwk/6z7XIJeUsSUg+ObvkEdogk5n6Y1Ea\nt5LxMpQzhG6SHJ2f38VyKgv9e/jnwXI8eiejper6OeQEBG4+AedcLYi0V5SUMIgD\nX4bxT9+qCwYrwt9YHkJySk237WZUWJPVfxHg0vqNYyD/CXBowx0nm8jEuZ8iT+CW\nO2uZq+0DO2WqoYT54lZux6aEzm+oAkzwJJVXJcUVPg7bJXK1ObOzvHpkZJxHL8+S\nKufzew/CXALKWHoCkEP/P8b7oxjcjQI3KK0EM2fABNvN28+qscqTqQjfAsNw24Ob\nP8rL8amgd/x7iddIbEpOSoLAH1gVoxJXA0oqkC6YmQKCAQEAiIeoomW1nUgTdCLf\nrrfyzUnaoqgVIpf42RKa319OnQD+GJg2iSAFwBuvovE3XN4H2YqW3Thri7LyVP+M\nxM+WSkl2tzLMXcUcF4staXvbyeoTVQ0xQzrFrT53aa/IIsEGvntkC/y0awQ6937w\nylWMLvF6BYNNi2+nBjx+//xl5/pfRwbS1mltJkOr2ODXM2IQT9STyc44JU0jak4m\n58Kd44IuiD+6BaPSwKn7KnEhPIeQO4z9bFJyKn3fVIL/5Pa9smEXAjEmS1Rj/ldM\n7eHzPvwlA9p9SFaKJt5x8G25ROCyB1x4RlBEreyutofcCoDSV+8DRPnEY2XN3RhS\nBgCW+wKCAQAyHrqaDSyS2YUXA/UaN59CYlZk9PYmssTa+16+vRfyH+1H0NQpsgd+\neTq4ze3ORpZ3adVN4svxNQ0JjvDVtZkxFPd70aoDJDKL5UqoU3QfDGHCb75FhpiO\n+ze+IVAXf3Ly+pvbU9Edp8PjAsnBqaA9743orXHhYmgJLRtmJWZv/6R3P9ncxLAW\nz9yOXaBu5TmSTBuNsBV9mhs8QQoUjyDJ7f+0yolBJMfAIGnW5EhbkK31pPvhHIrC\nRn4yCr1mW9F77KNpNMMq0BTFD7jE4SFLvRPThSem0Z5Xr8wwxbDJSa7H7DgyhryE\ng6Qp42AwVpdZ/mqfjNdGeWWBQ2UzVxcZAoIBAHNXgjD3umcKciYRAbltNJrXx9xk\ndAv8I69oEMCy4hCmvKUjy/UI9NqXFjBb/G6VGgh6NUE9o9o27t1Y5Plm0izyCA1M\nDFruaRfjyJ8qjbEifcqRtcF3rzsBiXIwdmbN6qT4PUipN2elpUAd7J1OIwGIIe3u\nCWNyOTNL+2+oQ/Eg1Y99mg3yrsVyOwhynVE80/X5cy07bXXR5rv1x4NKSVbPhlnt\nL6J5iAoqoDKICzjcgF5x3mj9YFWZrC3aRxRrN5RoEgeVdcXeK56UJqXHjmKN++m3\nc8OPEIBZiD8UJuhSNSOLiBFrGz6toy6rpHavqqknGhVWotXsAs1h8LNkBe8=\n-----END RSA PRIVATE KEY----- - - SSH_HOST=ssh - - SSH_PORT=2020 - - API_HOST=api - - API_PROTOCOL=http - - API_PORT=3000 - volumes: - - ./tests:/ansible - labels: - lagoon.type: none - local-git: - image: ${IMAGE_REPO:-lagoon}/local-git - environment: - - GIT_AUTHORIZED_KEYS=ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDEZlms5XsiyWjmnnUyhpt93VgHypse9Bl8kNkmZJTiM3Ex/wZAfwogzqd2LrTEiIOWSH1HnQazR+Cc9oHCmMyNxRrLkS/MEl0yZ38Q+GDfn37h/llCIZNVoHlSgYkqD0MQrhfGL5AulDUKIle93dA6qdCUlnZZjDPiR0vEXR36xGuX7QYAhK30aD2SrrBruTtFGvj87IP/0OEOvUZe8dcU9G/pCoqrTzgKqJRpqs/s5xtkqLkTIyR/SzzplO21A+pCKNax6csDDq3snS8zfx6iM8MwVfh8nvBW9seax1zBvZjHAPSTsjzmZXm4z32/ujAn/RhIkZw3ZgRKrxzryttGnWJJ8OFyF31JTJgwWWuPdH53G15PC83ZbmEgSV3win51RZRVppN4uQUuaqZWG9wwk2a6P5aen1RLCSLpTkd2mAEk9PlgmJrf8vITkiU9pF9n68ENCoo556qSdxW2pxnjrzKVPSqmqO1Xg5K4LOX4/9N4n4qkLEOiqnzzJClhFif3O28RW86RPxERGdPT81UI0oDAcU5euQr8Emz+Hd+PY1115UIld3CIHib5PYL9Ee0bFUKiWpR/acSe1fHB64mCoHP7hjFepGsq7inkvg2651wUDKBshGltpNkMj6+aZedNc0/rKYyjl80nT8g8QECgOSRzpmYp0zli2HpFoLOiWw== ansible-testing - ports: - - '2222:22' - labels: - lagoon.type: none - remotedev: - image: jhen0409/remotedev-server - command: node main.js - environment: - - ADAPTER= - - PORT=9090 - ports: - - '9090:9090' - labels: - lagoon.type: none - local-api-data-watcher-pusher: - depends_on: - - api-db - image: ${IMAGE_REPO:-lagoon}/local-api-data-watcher-pusher - volumes: - - ./local-dev/api-data:/api-data - - ./local-dev/api-data-watcher-pusher:/home - labels: - lagoon.type: none - local-minio: - image: minio/minio - entrypoint: sh - command: -c 'mkdir -p /export/lagoon-files && /usr/bin/minio server /export' - ports: - - '9000:9000' - environment: - - MINIO_ACCESS_KEY=minio - - MINIO_SECRET_KEY=minio123 - labels: - lagoon.type: none - drush-alias: - image: ${IMAGE_REPO:-lagoon}/drush-alias - volumes: - - ./services/drush-alias/web/aliases.drushrc.php.stub:/app/aliases.drushrc.php.stub - ports: - - '8087:8080' - labels: - lagoon.type: custom - lagoon.template: services/drush-alias/.lagoon.app.yml - lagoon.image: amazeeiolagoon/drush-alias:v0-22-0 - version: '2' - logs-db: - image: ${IMAGE_REPO:-lagoon}/logs-db - user: '111111111' - environment: - KEYCLOAK_URL: http://docker.for.mac.localhost:8088 - ports: - - '9200:9200' - labels: - lagoon.type: elasticsearch - lagoon.template: services/logs-db/.lagoon.single.yml - lagoon.image: amazeeiolagoon/logs-db:v0-22-0 - logs-forwarder: - image: ${IMAGE_REPO:-lagoon}/logs-forwarder - user: '111111111' - labels: - lagoon.type: custom - lagoon.template: services/logs-forwarder/.lagoon.single.yml - lagoon.image: amazeeiolagoon/logs-forwarder:v0-22-0 - logs-db-ui: - image: ${IMAGE_REPO:-lagoon}/logs-db-ui - user: '111111111' - ports: - - '5601:5601' - environment: - KEYCLOAK_URL: http://docker.for.mac.localhost:8088 - LOGSDB_UI_URL: http://0.0.0.0:5601 - labels: - lagoon.type: kibana - lagoon.template: services/logs-db-ui/.lagoon.yml - lagoon.image: amazeeiolagoon/logs-db-ui:v0-22-0 - logs-db-curator: - image: ${IMAGE_REPO:-lagoon}/logs-db-curator - user: '111111111' - labels: - lagoon.type: cli - lagoon.template: services/logs-db-curator/.lagoon.app.yml - lagoon.image: amazeeiolagoon/logs-db-curator:v0-22-0 - logs2logs-db: - image: ${IMAGE_REPO:-lagoon}/logs2logs-db - user: '111111111' - command: - - '--config.reload.automatic' - - '--config.reload.interval' - - '1s' - ports: - - '5140:5140/udp' - - '5141:5141/udp' - volumes: - - './services/logs2logs-db/pipeline:/usr/share/logstash/pipeline' - labels: - lagoon.type: logstash - lagoon.template: services/logs2logs-db/.lagoon.yml - lagoon.image: amazeeiolagoon/logs2logs-db:v0-22-0 - auto-idler: - image: ${IMAGE_REPO:-lagoon}/auto-idler - user: '111111111' - volumes: - - './services/auto-idler/idle-services.sh:/idle-services.sh' - - './services/auto-idler/idle-clis.sh:/idle-clis.sh' - - './services/auto-idler/create_jwt.sh:/create_jwt.sh' - labels: - lagoon.type: custom - lagoon.template: services/auto-idler/.lagoon.yml - lagoon.image: amazeeiolagoon/auto-idler:v0-22-0 - storage-calculator: - image: ${IMAGE_REPO:-lagoon}/storage-calculator - user: '111111111' - volumes: - - './services/storage-calculator/calculate-storage.sh:/calculate-storage.sh' - labels: - lagoon.type: custom - lagoon.template: services/storage-calculator/.lagoon.yml - lagoon.image: amazeeiolagoon/storage-calculator:v0-22-0 - logs-collector: - image: openshift/origin-logging-fluentd:v3.6.1 - labels: - lagoon.type: custom - lagoon.template: services/logs-collector/.lagoon.yml - lagoon.rollout: daemonset diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md deleted file mode 100644 index ecda652bc..000000000 --- a/docs/SUMMARY.md +++ /dev/null @@ -1,17 +0,0 @@ -# Summary - ---- - -This page contains descriptions and links to the documentation within the `docs/` folder. - ---- - -| Page | Description | -|:--------------------------|:----------------------| -| [Helm](helm.md) | Provides details of how to install [Helm](https://helm.sh) into OpenShift. | -| [Metrics Install](metrics_install.md) | Provides details of how to install Prometheus and Grafana, as used in the Metrics solution. | -| [Metrics Dashboards](metrics_dashboards.md) | Provides details of the Grafana dashboards. | -| [Metrics Charts](metrics_charts.md) | Provides details of the Helm Charts used for the Metrics solution. | -| [Tests](tests.md) | Provides details of the tests that have been created. | -| [Troubleshooting](troubleshooting.md) | Troubleshooting hints and tips. | -| [Links](links.md) | Useful links. | \ No newline at end of file diff --git a/docs/administering_lagoon/create-project.gql b/docs/administering_lagoon/create-project.gql deleted file mode 100644 index efd28814c..000000000 --- a/docs/administering_lagoon/create-project.gql +++ /dev/null @@ -1,77 +0,0 @@ -# See the docs for a detailed explanation about this file: -# https://lagoon.readthedocs.io/en/latest/administering_lagoon/graphql_api/#create-first-project - -# 1. Create a customer -mutation { - addCustomer( - input: { - # TODO: Fill in the name field - # This is the unique identifier of the customer - name: "" - # TODO: Fill in privateKey field - # The private key is a string, with new lines represented by `\n` - # See example here: https://github.com/amazeeio/lagoon/blob/66a080fa5cd0da5a0dca05f2532055f055842cba/local-dev/api-data/api-data.gql#L163 - privateKey: "" - } - ) { - name - # TODO: Make a note of the customer ID that comes back in the response - id - } -} - -# 2. Create an OpenShift -mutation { - addOpenshift( - input: { - # TODO: Fill in the name field - # This is the unique identifier of the OpenShift - name: "" - # TODO: Fill in consoleUrl field - # This is the URL of the OpenShift console (without any `/console` suffix) - consoleUrl: "" - # TODO: Fill in the token field - # This is the token of the `lagoon` service account created in this OpenShift (this is the same token that we also used during installation of Lagoon) - token: "" - } - ) { - name - # TODO: Make a note of the openshift ID that comes back in the response - id - } -} - -# 3. Create a project and assign it the customer and OpenShift -mutation { - addProject( - input: { - # TODO: Fill in the name field - # This is the unique identifier of the project - name: "" - # TODO: Fill in the customer field - # This is the customer ID from the response of the first query - customer: 0 - # TODO: Fill in the openshift field - # This is the OpenShift ID from the response of the first query - openshift: 0 - # TODO: Fill in the gitUrl field - # This is the SSH URL to the Git repository where a `.lagoon.yml` file should be committed in the root. - # HTTPS URLs are currently not supported. - gitUrl: "" - } - ) { - name - customer { - name - } - openshift { - name - } - gitUrl - activeSystemsDeploy - activeSystemsPromote - activeSystemsRemove - branches - pullrequests - } -} diff --git a/docs/administering_lagoon/graphql_api.md b/docs/administering_lagoon/graphql_api.md deleted file mode 100644 index 220abb3a1..000000000 --- a/docs/administering_lagoon/graphql_api.md +++ /dev/null @@ -1,405 +0,0 @@ -# GraphQL API - -## Running GraphQL queries - -Direct API interactions in Lagoon are done via GraphQL. - -In order to authenticate with the API, we need a JWT (JSON Web Token) that allows us to use the GraphQL API as admin. To generate this token, open the terminal of the `auto-idler` pod via the OpenShift UI or `oc rsh` on the command line and run the following command: - -``` -./create_jwt.sh -``` - -This will return a long string which is the JWT token. Make a note of this as we will need it to send queries. - -We also need the URL of the API endpoint, which can be found under "Routes" in the OpenShift UI or `oc get route api` on the command line. Make a note of this endpoint URL, which we will also need. - -To compose and send GraphQL queries, we recommend [GraphiQL.app](https://github.com/skevy/graphiql-app), a desktop GraphQL client with features such as autocomplete. To continue with the next steps, install and start the app. - -Under "GraphQL Endpoint", enter the API endpoint URL with `/graphql` on the end. Then click on "Edit HTTP Headers" and add a new header: - -- "Header name": `Authorization` -- "Header value": `Bearer [JWT token]` (make sure that the JWT token has no spaces, as this would not work) - -Press ESC to close the HTTP header overlay and now we are ready to send the first GraphQL request! - -Enter this in the left panel - -```graphql -{ - allProjects { - name - } -} -``` - -And press the ▶️ button (or press CTRL+ENTER). If all went well, your first GraphQL response should appear shortly afterwards in the right pane. - -## Creating the first project - -Let's create the first project for Lagoon to deploy! For this we'll use the queries from the GraphQL query template in [`create-project.gql`](https://github.com/amazeeio/lagoon/blob/master/docs/administering_lagoon/create-project.gql). - -For each of the queries (the blocks starting with `mutation {`), fill in all of the empty fields marked by TODO comments and run the queries in GraphiQL.app. This will create one of each of the following three objects: - -1. `customer` The customer of the project. Can be used for an actual customer (if you use Lagoon in a multi-customer setup), or just to group multiple projects together. `customer` will hold the SSH private key that Lagoon will use to clone the Git repository of the project. -2. `openshift` The OpenShift cluster that Lagoon should deploy to. Lagoon is not only capable of deploying to its own OpenShift but also to any OpenShift anywhere in the world. -3. `project` The project to be deployed, which is a git repository with a `.lagoon.yml` configuration file committed in the root. - -## Allowing access to the project - -In Lagoon each developer authenticates via their SSH key(s). This determines their access to: - -1. The Lagoon API, where they can see and edit projects they have access to -2. Remote Shell Access to containers that are running in projects they have access to -3. The Lagoon logging system, where a developer can find request logs, container logs, Lagoon logs and more. - -To allow access to the project, we first need to add a new user to the API: - -```graphql -mutation { - addUser( - input: { - email: "michael.schmid@example.com" - firstName: "Michael" - lastName: "Schmid" - comment: "CTO" - } - ) { - # TODO: Make a note of the user ID that is returned - id - } -} -``` - -Then we can add an SSH public key for the user to the API: - -```graphql -mutation { - addSshKey( - input: { - # TODO: Fill in the name field - # This is a non-unique identifier for the SSH key - name: "" - # TODO: Fill in the keyValue field - # This is the actual SSH public key (without the type at the beginning and without the comment at the end, ex. `AAAAB3NzaC1yc2EAAAADAQ...3QjzIOtdQERGZuMsi0p`) - keyValue: "" - # TODO: Fill in the keyType field - # Valid values are either SSH_RSA or SSH_ED25519. - keyType: SSH_RSA - # TODO: Fill in the userId field - # This is the user ID that we noted from the addUser query - userId: 0 - } - ) { - id - } -} -``` - -After we added the key we can grant the user access to either: - -**Grant a user access to a single project** - -```graphql -mutation { - addUserToProject( - input: { - # TODO: Fill in the project field - # This is the project name - project: "" - # TODO: Fill in the userId field - # This is the user ID that we noted from the addUser query - userId: 0 - } - ) { - id - } -} -``` - -**Grant a user access to a customer (which will grant access to all projects of the customer)** - -```graphql -mutation { - addUserToCustomer( - input: { - # TODO: Fill in the customer field - # This is the customer name - customer: "" - # TODO: Fill in the userId field - # This is the user ID that we noted from the addUser query - userId: 0 - } - ) { - id - } -} -``` - -After running one or more of these kinds of queries, the user will be granted access to create tokens via SSH, access containers and more. - -## Adding notifications to the project - -If you want to know what is going on during a deployment, we suggest configuring notifications for your project, which provide: - -- Push messages -- Build start information -- Build success or failure messages -- Many more - -As notifications can be quite different of their information they need, each notification type has its own mutation. - -As with users, we first add the notification: - -```graphql -mutation { - addNotificationSlack( - input: { - # TODO: Fill in the name field - # This is your own identifier for the notification - name: "" - # TODO: Fill in the channel field - # This is the channel for the message to be sent to - channel: "" - # TODO: Fill in the webhook field - # This is the URL of the webhook where messages should be sent, this is usually provided by the chat system to you - webhook: "" - } - ) { - id - } -} -``` - -After the notification is created, we can now assign it to our project: - -```graphql -mutation { - addNotificationToProject( - input: { - notificationType: SLACK - # TODO: Fill in the project field - # This is the project name - project: "" - # TODO: Fill in the notification field - # This is the notification name - notificationName: "" - } - ) { - id - } -} -``` - -Now for every deployment you will receive messages in your defined channel. - -## Example GraphQL queries - -### Adding a new OpenShift target - -The OpenShift cluster that Lagoon should deploy to. Lagoon is not only capable of deploying to its own OpenShift but also to any OpenShift anywhere in the world. - -```graphql -mutation { - addOpenshift( - input: { - # TODO: Fill in the name field - # This is the unique identifier of the OpenShift - name: "" - # TODO: Fill in consoleUrl field - # This is the URL of the OpenShift console (without any `/console` suffix) - consoleUrl: "" - # TODO: Fill in the token field - # This is the token of the `lagoon` service account created in this OpenShift (this is the same token that we also used during installation of Lagoon) - token: "" - } - ) { - name - id - } -} -``` - -### Adding a new customer - -This query adds a customer which can be assigned one or more projects. Can be used for an actual customer (if you use Lagoon in a multi-customer setup), or just to group multiple projects together. Each customer has an SSH private key that Lagoon will use to clone the Git repository of the project. - -```graphql -mutation { - addCustomer( - input: { - # TODO: Fill in the name field - # This is the customer name - name: "" - # TODO: Fill in the privateKey field - create a new private and public keypair with `ssh-keygen` - # The private key is a string, with new lines represented by `\n` - privateKey: "" - } - ) { - name - id - } -} -``` - -### Adding a new project - -This query adds a new project to be deployed, which is a git repository with a `.lagoon.yml` configuration file committed in the root. - -```graphql -mutation { - addProject( - input: { - # TODO: Fill in the name field - # This is the project name - name: "" - # TODO: Fill in the customer field - # This is the id of the customer to assign to the project - customer: 0 - # TODO: Fill in the openshift field - # This is the id of the OpenShift to assign to the project - openshift: 0 - # TODO: Fill in the name field - # This is the project name - gitUrl: "" - } - ) { - name - customer { - name - id - } - openshift { - name - id - } - gitUrl - activeSystemsDeploy - activeSystemsRemove - branches - pullrequests - } -} -``` - -### List projects and customers - -This is a good query to see an overview of all projects, OpenShifts and customers that exist within our Lagoon. - -```graphql -query { - allProjects { - name - gitUrl - } - allOpenshifts { - name - id - } - allCustomers { - name - id - } -} -``` - -### Single project - -If you want a detailed look at a single project, this query has been proven quite good: - -```graphql -query { - projectByName( - # TODO: Fill in the project name - name: "" - ) { - id - branches - gitUrl - pullrequests - productionEnvironment - notifications(type: SLACK) { - ... on NotificationSlack { - name - channel - webhook - id - } - } - environments { - name - deployType - environmentType - } - openshift { - id - } - customer { - id - name - sshKeys { - id - name - } - } - } -} -``` - -### Querying a project by its Git URL - -Don't remember the name of a project, but know the Git URL? Search no longer, there is an GraphQL Query for that: - -```graphql -query { - projectByGitUrl(gitUrl: "git@server.com:org/repo.git") { - name - } -} -``` - -### Updating objects - -The Lagoon GraphQL API cannot only display objects and create objects, it also has the capability to update existing objects, using [a patch object](https://blog.apollographql.com/designing-graphql-mutations-e09de826ed97). - -Update the branches to deploy within a project: - -```graphql -mutation { - updateProject( - input: { id: 109, patch: { branches: "^(prod|stage|dev|update)$" } } - ) { - id - } -} -``` - -Update the production environment within a project (important: this needs a redeploy in order for the changes to be reflected in the containers): - -```graphql -mutation { - updateProject( - input: { id: 109, patch: { productionEnvironment: "master" } } - ) { - id - } -} -``` - -You can also combine multiple changes at once: - -```graphql -mutation { - updateProject( - input: { - id: 109 - patch: { - productionEnvironment: "master" - branches: "^(prod|stage|dev|update)$" - } - } - ) { - id - } -} -``` diff --git a/docs/administering_lagoon/install.md b/docs/administering_lagoon/install.md deleted file mode 100644 index ca414abb0..000000000 --- a/docs/administering_lagoon/install.md +++ /dev/null @@ -1,67 +0,0 @@ -# Install Lagoon on OpenShift - -Lagoon is not only capable to deploy into OpenShift, it actually runs in OpenShift. This creates the just tiny chicken-egg problem of how to install Lagoon on an OpenShift when there is no Lagoon yet. - -Luckily we can use the local development environment to kickstart another Lagoon in any OpenShift, running somewhere in the world. - -Check the [Requirements for OpenShift by Lagoon](/administering_lagoon/openshift_requirements.md) before continuing. - -This process consists of 3 main stages, which are in short: - -1. Configure existing OpenShift -2. Configure and connect local Lagoon with OpenShift -3. Deploy! -4. Configure Installed Lagoon - -### Configure existing OpenShift - -Hint: This also works with the OpenShift provided via MiniShift that can be started via `make openshift`. - -In order to create resources inside OpenShift and push into the OpenShift Registry, Lagoon needs a Service Account within OpenShift \([read more about Service Accounts](https://docs.openshift.org/latest/dev_guide/service_accounts.html)\). - -Technically Lagoon can use any Service Account and also needs no admin permissions, the only requirement is that the `self-provisioner` role is given to the Service Account. - -In this example we create the Service Account `lagoon` in the OpenShift Project `default`. - -1. Login into OpenShift as an Admin \(we assume that you have the oc cli tools already installed. If not, please see [here](https://docs.openshift.org/latest/cli_reference/get_started_cli.html#cli-reference-get-started-cli)\) - - oc login - -2. Run the openshift-lagoon-setup script - - make openshift-lagoon-setup - -3. At the end of this script it will give you a serviceaccount token, keep that somewhere safe. - -### Configure and connect local Lagoon with OpenShift - -In order to use a local Lagoon to deploy itself on an OpenShift, we need a subset of Lagoon running locally. We need to tech this local Lagoon how to connect to the OpenShift: - -1. Edit `lagoon` inside local-dev/api-data/01-populate-api-data.gql, in the `Lagoon Kickstart Objects` section: - - 1. `[REPLACE ME WITH OPENSHIFT URL]` - The URL to the OpenShift Console, without `console` at the end. - 2. `[REPLACE ME WITH OPENSHIFT LAGOON SERVICEACCOUTN TOKEN]` - The token of the lagoon service account that was shown to you during `make openshift-lagoon-setup` - -2. Build required Images and start services: - - make lagoon-kickstart - - This will do the following: - - 1. Build all required Lagoon service Images (this can take a while) - 2. Start all required Lagoon services - 3. Wait 30 secs for all services to fully start - 4. Trigger a deployment of the `lagoon` sitegroup that you edited further, which will cause your local lagoon to connect to the defined OpenShift and trigger a new deployment - 5. Show the logs of all Local Lagoon Services - -3. As soon as you see messages like `Build lagoon-1 running` in the logs it's time to connect to your OpenShift and check the build. The URL you will use for that depends on your system, but it's most probably the same as in `openshift.console`. Then you should see a new OpenShift Project called `[lagoon] develop` and in there a `Build` that is running. On a local OpenShift you can find that under https://192.168.99.100:8443/console/project/lagoon-develop/browse/builds/lagoon?tab=history. If you see the Build running check the logs and see how the deployment system does it's magic! This is your very first Lagoon deployment running! 🎉 Congrats! - - Short background on what is actually happening here: - - Your local running Lagoon (inside docker-compose) received a deploy command for a project called `lagoon` that you configured. In this project it is defined to which OpenShift that should be deployed (one single Lagoon can deploy into multiple OpenShifts all around the world). So the local running Lagoon service `openshiftBuildDeploy` connects to this OpenShift and creates a new project, some needed configurations (ServiceAccounts, BuildConfigs, etc.) and triggers a new Build. This Build will run and deploy another Lagoon within the OpenShift it runs. - -4. As soon as the build is done, go to the `Application > Deployments` section of the OpenShift Project and you should see all the Lagoon Deployment Configs deployed and running. Also go to `Application > Routes` and click on the generated route for `rest2tasks` (for a local OpenShift this will be http://rest2tasks-lagoon-develop.192.168.99.100.xip.io/), if you get `welcome to rest2tasks` as result, you did everything correct, bravo! - -### Configure Installed Lagoon - -We have now a fully running Lagoon. Now it's time to configure the first project inside of it. Follow the examples in [GraphQL API](/administering_lagoon/graphql_api.md) diff --git a/docs/administering_lagoon/openshift_requirements.md b/docs/administering_lagoon/openshift_requirements.md deleted file mode 100644 index 5c2cb4737..000000000 --- a/docs/administering_lagoon/openshift_requirements.md +++ /dev/null @@ -1,30 +0,0 @@ -# OpenShift Requirements by Lagoon - -Lagoon tries to run on a standard installation of OpenShift as possible, but it expects some things: - - -### OpenShift Version - -Currently Lagoon is tested and supported with OpenShift 3.9. - -### Permissions - -In order to setup Lagoon in an OpenShift you need a cluster-admin account to run the initial setup via `make lagoon-kickstart`. With this Lagoon will create it's own Roles and Permissions and the cluster-admin is not needed anymore. - -### PV StorageClasses - -For deployment projects by Lagoon the following StorageClasses will be needed: - -| Name | Used for | Description | -| -----| ------ |------| -| default | Single Pod mounts (mariadb, solr) | The default StorageClass will be used for any single pod mounts like mariadb, solr, etc. Suggested to use SSD based Storage | -| `bulk` | multi pod mounts (drupal files) | `bulk` StorageClass will be used whenever a project requests storage that needs to be mounted into multiple pods at the same time. Like nginx-php-persistent which will mount the same PVC in all nginx-php pods. Suggested to be on SSD but not required. | - -Lagoon itself will create PVCs with the following StorageClasses: - -| Name | Used for | Description | -| -----| ------ |------| -| `lagoon-elasticsearch` | `logs-db` | `logs-db` will create PVCs with the storageClass name `lagoon-elasticsearch` for persistent storage of the elasticsearch. Standard deployments of `logs-db` create an Elasticsearch Cluster with 3 `live` nodes. Strongly suggested to be on SSD. | -| `lagoon-logs-db-archive` | `logs-db` | Beside the `live` nodes, `logs-db` also creates 3 `archive` nodes. These are used for elasticsearch data which is older than 1 month. Therefore it should be much bigger than `lagoon-elasticsearch` but can run on regular HDD. | -| `lagoon-logs-forwarder` | `logs-forwarder` | Used by `logs-forwarder` fluentd to provide a persistent buffer. Default configurations of Lagoon create 3 `logs-forwarder` pods. Preferred to be on SSD, but not needed. | - diff --git a/docs/clair.md b/docs/clair.md deleted file mode 100644 index d25b4d5a7..000000000 --- a/docs/clair.md +++ /dev/null @@ -1,5 +0,0 @@ -# Clair - ---- - -This document describes ... \ No newline at end of file diff --git a/docs/code_of_conduct.md b/docs/code_of_conduct.md deleted file mode 100644 index 1504414d8..000000000 --- a/docs/code_of_conduct.md +++ /dev/null @@ -1,46 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@amazee.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/docs/developing_lagoon/contributing.md b/docs/developing_lagoon/contributing.md deleted file mode 100644 index 87ccd831e..000000000 --- a/docs/developing_lagoon/contributing.md +++ /dev/null @@ -1,25 +0,0 @@ -# Contributing to Lagoon - -You would like to hack Lagoon? Yay 🎉! That's how we all started. At Lagoon we take pride in being able to run everything in a local environment, see [Developing Lagoon](/developing_lagoon/index.md) how this works. - -## I found a security issue - -We take security very seriously. If you discover a security issue or think you found one, please bring it to the maintainers attention. - -Please send your findings to hello@amazee.io. Please **DO NOT** file a GitHub issue for them. - -Security reports are greatly appreciated and will receive public Karma and Swag! We're also working on a Bug Bounty system. - -## I found an issue - -We're always interested in fixing issues, therefore issue reports are very welcome. Please make sure to check that your issue does not already exist in the [issue list](https://github.com/amazeeio/lagoon/issues) - -## I got a feature request or idea - -Cool! Just create an [issue](https://github.com/amazeeio/lagoon/issues) and we're happy to look over it. We can't guarantee though that it will be implemented. But we are always interested in hearing ideas where we can bring Lagoon to. - -Another good way is also to talk to us via RocketChat about your idea. [Join today](https://amazeeio.rocket.chat/) in the channel #lagoon. - -## I wrote some code - -Epic! Please send us a Pull Request for it, we will do our best to review it and merge it if possible. diff --git a/docs/developing_lagoon/index.md b/docs/developing_lagoon/index.md deleted file mode 100644 index 21cb6ba3b..000000000 --- a/docs/developing_lagoon/index.md +++ /dev/null @@ -1,89 +0,0 @@ -# Development of Lagoon - -Development of Lagoon happens locally via Docker. We are using the new [Docker Multi Stage builds](https://docs.docker.com/engine/userguide/eng-image/multistage-build/) very heavily, so it requires at least Docker Version 17.06.1. - -## Install Docker - -Please check the [official Docs of Docker](https://docs.docker.com/engine/installation/) how to install Docker. - -### On Linux Install Docker Compose - -Docker compose is included in Docker for Mac installations. For linux installations see the directions here: [https://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/). - -## Start Services - -1. Add `192.168.99.0/24` to insecure registries in Docker (see [here](https://docs.docker.com/registry/insecure/) how to do that). Also make sure that you give your Docker Host minimum 4 CPUs and 4GB Ram. - - -Important: Lagoon consists of a lot of Services and Docker Images, building and running them locally might not even be necessary. -We're using make (see the [Makefile](https://github.com/amazeeio/lagoon/blob/master/Makefile)) in order to only build the needed Docker Images specifically for a part of Lagoon. - -All of it is based around tests. So if you like to only build the part that is needed to work on the Node.js deployment, you can run the tests with `make tests/node`, this will then setup (openshift, building images, services) all the needed stuff for the Node.js deployment part. - -If you would still like to build and start all services, go ahead: - -2. Build images - -```sh -make build -``` - -3. start Lagoon Services - -```sh -make up -``` - -4. Follow the Services logs - -```sh -make logs -``` - -5. run tests (read [Tests](tests.md) to learn more about testing) -```sh -make tests -``` - -6. Look what happens in OpenShift: [https://192.168.99.100:8443/console](https://192.168.99.100:8443/console) (developer/developer) - -## Local Development - -Most services are written in Node.js. As many of these services share similar Node code and Node Packages, we're using a new feature of yarn, called `yarn workspaces`. Yarn Workspaces needs a package.json in the projects root directory that defines the workspaces. - -The development of the services can happen directly within Docker. Each container for each service is setup in a way that it's source code is mounted into the running container (see [docker-compose.yml](../using_lagoon/docker-compose_yml.md). Node itself is watching the code via `nodemon` and restarts the node process automatically on a change. - -### lagoon-commons - -The services not only share many node packages, but also share actual custom code. This code is within `node-packages/lagoon-commons` it will be automatically symlinked by yarn workspaces, plus the nodemon of the services is setup in a way that it also checks for changes in `node-packages` and will restart the node process automatically. - -### Hiera - -The API uses a puppet compatible yaml format to store it's data. On production this hiera is in another git repository. For local development there is a folder `local-hiera` which contains testdata that is used during development and testing, plus has no client related data in them. For easier development there is `local-hiera-watcher-pusher` which watches the `local-hiera` folder and on every changes pushes the changes into `local-git-server` which emulates a git server like it is on production. The api service is connecting to this local git server and updates it's data from it. - -## Troubleshooting - -**I can't build any docker image for any Node.js based service** - -Rebuild the images via - -```sh -make clean -make build -``` - -**I get errors about missing node_modules content when I try to build / run a NodeJS based image** - -Make sure to run `yarn` in lagoon's root directory, since some services have common dependencies managed by `yarn` workspaces. - -**My builds can't resolve domains** - -Some ISPs set up a "search domain" to catch domain name errors. Virtualbox will copy this setting -into minishift which can cause domain resolution errors in the openshift pods. To check for this -problem, look at the `/etc/resolv.conf` in your failing pod and check for errant search domains. - -![OpenShift pod resolver settings](../images/pod_search_domains.jpg) - -To fix, you must remove the extra search domain. Login to the minishift vm (`minishift ssh`) and -remove the setting from `/etc/resolv.conf`. Restart openshift docker, `sudo docker restart origin`. -Redeploy `docker-host` in the `lagoon` project. diff --git a/docs/developing_lagoon/tests.md b/docs/developing_lagoon/tests.md deleted file mode 100644 index f914faf08..000000000 --- a/docs/developing_lagoon/tests.md +++ /dev/null @@ -1,54 +0,0 @@ -# Lagoon testing - -Our tests are all written with Ansible and mostly follow this approach: - -1. They create a new git repository -2. Add and commit some files from a list of files (in `tests/files`) into this git repository -3. Push this git repository into a git server (either locally or on Github) -4. Send a trigger to a trigger service (for example a Webhook to the Webhook Handler which is the same as a real webhook that would be sent) -5. Starts to monitor the URL that the test would expect something to happen (like deploying a nodejs app that has the git branch as an HTML text) -6. Compares the result on the URL with the expected result - -Lagoon is mostly tested in 3 different ways: - -## 1. Locally - -During local development the best and easiest is to test locally. All tests are started via make. Make will download and build all the required dependencies. - - make tests - -This would run all tests defined. If you like only to run a subset of the tests, run `make tests-list` to see all tests that exist and run them individually like `make tests/node` to run the nodejs Docker Images tests - -In order to actually see what is happening inside the microservices, we can use `make logs`: - - make logs - -Or only for a specific service: - - make logs service=webhook-handler - -Sometimes you would like to see what is happening inside the Jenkins, it can be found here: http://localhost:8888/ (`admin`:`admin`) - -Sometimes you just would like to create another push webhook, without to wait for the git repository to be initialized and being pushed. For this case there is a small helper script `tests/playbooks/helpers/just-push.yaml` that will get the current head of the git repository and push a webhook push. It needs to know which git repository and branch you would like to check and push: - - docker-compose -p lagoon exec tests ansible-playbook /ansible/tests/tests/helpers/just-push.yaml -e git_repo_name=node.git -e branch=develop - -## 2. Automated integration testing - -In order to test pull requests that are created against Lagoon, we have a full automatic integration test running on TravisCI: https://travis-ci.org/amazeeio/lagoon. It is defined inside the `.travis.yml` and runs automatically for every pull request that is opened. - -This will build all Images, start an OpenShift and run all tests - -## 3. Real World Testing - -To make sure that our services also work in the real world (e.g. deployed on OpenShift with real URLs, real git repositories and stuff), we also have tests for this. Currently we only deploy the `develop` and `master` branches to a real OpenShift infrastructure. - -For these tests we use the exact same Ansible scripts like the local or the automated testing, we just push to an actual Github repository https://github.com/amazeeio-ci-testing and send webhooks to the webhook-handler that are running OpenShift. - -The tests are defined in `Jenkinsfile.testing-develop` and `Jenkinsfile.testing-master`. They get their testing infrastructure (endpoints, etc.) from a docker-compose.yaml file within the `tests` folder. - -Beside of that it's exactly the same as the automated integration testing. - -The tests can be found here: -- `develop` branch: https://lagoon-ci.amazeeio.cloud/job/lagoon-test-develop/ -- `master` branch: https://lagoon-ci.amazeeio.cloud/job/lagoon-test-master/ diff --git a/docs/helm.md b/docs/helm.md deleted file mode 100644 index 9cd8edf88..000000000 --- a/docs/helm.md +++ /dev/null @@ -1,63 +0,0 @@ -# Helm - ---- - -This document describes how to install [Helm](https://helm.sh) inside an OpenShift cluster. - -A more comprehensive guide can be found [here](https://blog.openshift.com/getting-started-helm-openshift/). - ---- - -## Instructions - -**Notes**
- -* To execute these instructions you must be logged into OpenShift / [MiniShift](https://github.com/minishift/minishift) as a cluster administrator. For local setup, install MiniShift first (`brew cask install minishift`) -* You must have the `oc` command installed. If you have installed MiniShift then you already have it. -* Helm v2.7.0 is used. - -The installation instructions for Helm can be found [here](https://github.com/kubernetes/helm#install). -***For local install in Mac OS X*** -****Note on VM Driver**** -By default Minishift is set to use the `xhyve` virtualization driver. If you have another driver available, for example `virtualbox`, use the `--vm-driver` flag. - -```console -$ brew install kubernetes-helm -$ minishift start --vm-driver virtualbox -``` -Once your Minishift is running (`minishift status`), skip to the `Create new project` section. - -****The instructions to install Helm on Linux are below.**** - -```console -$ curl -s https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-linux-amd64.tar.gz | tar xz -$ cp linux-amd64/helm /usr/local/bin/ -$ helm init --client-only -``` - -****Create a new project and set the Helm namespace environment variable.**** - -```console -$ oc new-project tiller -$ export TILLER_NAMESPACE=tiller -``` - -****Create the required OpenShift resources and install `tiller` (the Helm server-side component)**** -Note that this command must be run from the root of the `bay` repository. - -```console -$ oc process -f manifests/helm/tiller-template.yaml \ --p TILLER_NAMESPACE="${TILLER_NAMESPACE}" | oc create -f - -``` - -****Confirm that Helm has been installed**** -```console -$ helm version -``` -Note, that in the case you see an error `Error: cannot connect to Tiller`, then execute the command below. - -For each project that Helm needs to deploy to run the following command (when switched into the project). - -```console -$ oc policy add-role-to-user edit "system:serviceaccount:${TILLER_NAMESPACE}:tiller" -``` diff --git a/docs/images/SDP_Bay_product_logo_JPG.JPG b/docs/images/SDP_Bay_product_logo_JPG.JPG new file mode 100644 index 0000000000000000000000000000000000000000..8395e830bf768efc5062bc1a7c9c7ce460e5c8d1 GIT binary patch literal 82909 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

Nf`_^TbZ8o~66m4{=Ag#$aHM-$E@ zd!h@oGZ5?KglMxSAYwW8-I}qCxhzGnPM~X4l=7rXr z?%#CtLi^^sj=mmS215oYbJl$K&{6o;^4pIKy0URSh^jY-*6b1|R8F5Q&p@=RT0j3w z1j=Cku11l=GP3icEFh)LAl%?xIY=+G;BP)UWxIER4N-#w5CwLV)=$K zYn;EL8uA&R@W=w+D0O3!W?2tdUI)w{K2WS_mg$v!Om<-}-9F5L?Ic`Un) zm2sM6Lha*?f6tsvay8uy(>ht^*_Adm_^v(>&~BFHj7A&`MZ}|eoDu2m=zcyRzim0hV!AwdKeV;eft}XpOnE|776V( zwH>A!W3neoJzKvNPaN1-Xs`7z912B>mtbI_C~PqQPl{Pd`E%^>XAXSqLj0TjE=Ng} zzbnl+tE}QEDgE%e9!zZG)l__mh1Wytl`ZZ0-ng?W#yYgYaH*aRC9PvF%_YB|%<3)o zi^x#ple8@Z!y<3AmjQ!P*DP_+fg1dy8}>Im|9j;#fu+%sr}G*S5$^`+D3d{V2q{GB z-Q3Z5F!kPmcs1SSkzP{@+~Vb2Y;=}Mv61W5qUeMWhw1gS@;qGlINjc`S){~wQ*1G0w)W%3D ze=P)L5>Vxu-S1!Nv9vwq|;Z9*AJ>{ViNvDOG4EC^!qR{6awYA zaQGUhcmyRRlqJN&tzPf%e3uP2^N*jZE;~1tdM3o0JAI(D{i^d9+?4_kgxNUfFv~LK zp}0t7$uU=wHp};rh|3f5y0p>-Ba{!`XqExSL7Ha*rgpVnFDm}XZeNgcMlCw-X^gk` z=x$nIWjQ9ut`3$$6Ynq;a?Ev57&Qp#oY9(Zh zA+e%`DRU|#(2Lhv*k0(UuM}v&aT?+2WIh%}OVY|(CJi$T>1yq;j><6@BPeQn z#6S#s47xx}>%RyuaQ*c+0({zIA+GwgUYFNXkk^#53voc3j?Cx_#rmow>24EL66`q{ z5&USWT>$5t%}VhdPgc8<6b*sLEde=)RsaA1Wlo&MyT2WaRw*7J+;!y8nIAb&wBKZz zA0lR2=q_mfqB~_NhTVMfQo!5!>(kahRV$&_SN9)4O}5V7>EE%oa|Ypb0S$`BT=DT< z7x{VJ^`0ABWJttVyy)#*l!?7jiif@il!?a9@-~A3f)ck^N_lt!i6vMPmfF)h;z52! zIU5$B4)TZgLAjwl{SP6!gRX2>#PiUfA>eMF#EuZ5Vm~M!-}iY2hQLK|KBqTFfH=Y}8+AH5W3p zsJVd=g;?h&y?!)AxO!mo`Ez2*c6-F#JdZB+=DnnipC9m~2!qAAOF>-@H{;?_YB%Nu zZdu$XFMF4O;4C>8D*KpcKEf>6h4C&^=2nuRQy~xNw2!eJ;s$ zrhVQIejMRa4Gec!tMuR&5D3uTl9U{R?U+nL?XiS|yUrRk_ z`lScBl{ekf)#PNgD znO(Znd|q?JmM%YNteaD2b;UnLr-o#sBoMed@RJc(Nnx0T7%pSB=4^#ao=!(gucX_8 zhOti9GMw*q|MEL>{`2Z7i*}%p@fT%GhhUt(1HA}h=tuCRETo8+MWf^VdKEk2Hw{y< z+K4kkjn7NXnjN{8``%xy*KEB-h3R`w-_I-_%XiKs zBxK_AadF(wHX#agtb6$P4&K@^uj3H@{2i5Wxn%Ms`97UXd3ccq4YQn@B{y2|PD#*C zH=J7HW#qdZ0;6*C_)br86!Rwv3~r9>R_>NSOX1KySyHi%eW%ZS_&u#Z=@$FlV? zPBqO_iaKnJkW6^*GLa+Ygfw0MYA+8Z-mCTyhdX-rr_an6%k*D2IoQ7 z-A3s)(P{_Fa}fuIFOI18IT5hKclDYe;=>xsp(YME3A2RPA`ZlW{ z74MgZhay(!+X<7WGC(#GwIk3E2^+K*9L^{{-DAZEA6o3#9eiMp$1I67UQ|HT8HQ95 z*FO)=6!M7W_#OVPVx}N(8>92Jp!NJF}v|Ec9zG#yxKwAsT`|#sT9K5vz$rmp6 zA9DPM9RHae|823LoL53d!*e7%CARzH9bC}Uk0qZIQi2Fd?C%V(Gg@lkb8b)*)$kt$ zG>K~J)_+^kp>RgR-Tt`@_Lv9%SCgGXgb;2>$Nu;8X?4e38a<1E+AX!DZu6OfzQ|UG zww1E`Tk-l=1TXd27Ck{9m84--96WrnDxH%*#aPrAS!GF;T1Kdy3EO;AkKb$e7k)X+ zno)Wx*VirJ0Eym1mcdx>QGIuiH^B3V1m`#AM zim)gX!W5!nI>&L&4u+r++-Q16P*}fpk@E#yYstA4$HnuxfdLz~PG*;E{h>%WIJ_DP z&zBMIef5^nF4{XhpS-PeLM%?p{`)dkS+HfcP;7CvOF^-q^WRSFV6imj#tj$8Ef?8> z1BEjiyG4P93n@@T4L5)L7K%tKHp9MXZaV*m-)jZ`f9B2o0mFaq;uE@@{=EVJNvlu% zrtwck_@8fmTHD+IJl;QT@d+I!|Fr*q=jNx3?)Z1c`=@O_z0&?qhxwN`KVc-szZ~aZ zJ^Zvrpno;e|Nhy3B*Z^x^B)QE>m2!yg!q*Z|B(>?AjE$p#D65juS?<|#s8xc;^dB7 zeM$jxkz(_H(5n6Rh_|J$yV{i&w}}@mw+rW96xW)$kf0_H^)zeoIjW|!cwgOtRYt(Q zh^cr^*s-J-gbo04PVxmlJ=cA<>L@9DBqAH>JgLre%q5s*jX~sGX!f(w7!98a;|cE> zlS^nltJ4_UH* z>ca6eb;0{_n}+*(L3LV^n7L=Yb_z}+cRt)$T*X^L<3Bms?;#-SM8azE|s{9(QQ z-(UQnZ(--@6}hF^ddtn9Z^C+iI2dmu9f;dB$R2oV9i`+Q!k-wi=I%mEj zH7W^5ro1w~pyTz3p2=XSq#wN|_t1An%bWlYbI!(??|IcP7P9s>lWVyJ2&J0*1PwJS zAiQ%P84Pn41ZuLQ-{;abf`%8HnuO=wUdVDD+$YKv4dR+=IiIBhR?f#CB8nuxBAza& zH*a1qhASJN2kHbt1zMM_v@mnEKcWWAI{61l{RJ;8$Uj$l(Yz|7$7NjPDqUyLl28ko zUP)hCicst24`XpjN@V%U+?>)v7QWN;05b?+Mzb5Yras(G%~93n#B|uqb)(7!3u++R z&Nuf7GC0ZFF*2mX1l8A}-N`orXf}i}wf6~5+_oUS|9gh~;XnV+UxU7!95Q~_mA7O6 zBTB~gcDNS{9{x?qMCy?e$9R0d=ZM%AVe28u-TyH#44ElkO9*C+o&`>F6=MF4L5fdc_ zV3<0$RwkURCJ}_QcHH`3%)NI|Tlc%}%P)!J#5II&gGs;!1IAbuy_h(r*hYc~Nr+BN zk&Ngd5S_%8Dq=825+xQ!fCR#HOF|HX=?F{_O%!9g0AY%#2A`GR-shZq{=3<8_uR8) zV1}V+p|#exywCf5o}xuY+ie#GH{OQb`ecmsLQ6&}$L3tF_5(>NQR!>|@)JC;e~XUr-)0 zhV-2`MB3Fg&u+>%88f1ojyb)-v@IIZ3V)sG#L^)N9qW)GU9ISB;wKiX>h!J1cWeG4 z?_5J4qJkcL@cN#*u~oYNkh_Sb)@IX*G$yGrfaEtKEik1DK&RV#e-;a=wV9U=+O0hN z6fv>;#PY8(q1q?Nv8BmRv7@{=r|!7$xbfBWy~jDRR~q9k7~fKU?}wK>QXb&!9#+wg z>avdjCp(j`x_MInlSAy0arl4!1cU(3_013~JkMZK)oz*uI_C zHy`np-!qQ|i&~1*>nl>Qz-R5H&&u5kGNh!WY?4Um+%O`AElnjJK|#Cjpj7V>Z_Z`h zvzKV^9`CX3a_k{kqDn8;J#e*z#-tYWjnoqo+I%(H%%|P{2kD-*G4RQ+D-&t7JrfhU zM%Bhm{?Mm*=w%NpBv9nB0G@0o5qpO2c)Zg zP>>D;?xN4@a*?|o_36uD?Q4U#G)>H4yJ<<#27@{YSPF&m z5%#85-%Y2_yi;YOJ+YXkqM`yyNSIC_l-k&x3lo;Ak!AvX$InR9y@QMwR4d*EAzgi3 zPEXP_oa>!wYg0~Xs#{x!{^>ePqp9cG9l9YiNV_HCb|8N@=)T*_vhgBZ;%Z# zO|=BA$xj6y)~iTewk|cn;v(;dzaIw!Lk-ROIfE4Zy>2mVnn44!#g8}5m-SRn zh7KS^RMp*6^Uvts+aH8+8rc>TS>)zeRoQiaQUyp@sK9iy`MsU)83^FW>%}kq-*kdG@-o zd2Oreo9ja>pT$O2;%pA?j-f^62S)&dYBp|tR98Y_v**2-SOjP-WhG6IWuP452DHu8 ztVAK@hby=Upxa7S60v0d@AfMG_xlvq>adJv_dqZ);cs4nhc5);myqy2^F8ah=4%Ye z)E14xH#jv|GS<(Rjd?2obeBRXAz}DjM({fF02*MN&{p)26$w$zud;SCiEL4PWuGn3 zHc#CSUNNoSi`KG&1UD|Lm&>UVd)!76ISOApPjs}ISENe09#Jz6F_$S**6e1e_@nR^ z;W&-KN@d`Ms&$dm| z9I~PHZb%1dZIlH>5bOE#{vAX}Z2Hj%I-sL~G4-+P_jTzOpq3N;#%iF*aYo7eL~p7J zIwt--|F1gDe{B@EuYG(s3oHYFB#Zw^OfE)$n`C8)O6L&X&s#<{S}Aztb&IA&(?x_@ zbC1_oUbQDCSPkNv5>@=Xt2c`3=nuz=JbN86XWd;_78?i2w!M7;c1xCecGfL0DGMu2 zZC+dnNT$3S=|5$sPT}dH-91iLBPGPK`wJ{Q-Vb%!C`iF3;W{f%w?Zq6?dx#$rv<&j z{z8DCw38BQREW1CpZt)zXogi%x@4+D6Bu;l%W|9tz;6hWJD^9g$7}U$Uc@HVsU#}n zt09l;xsuaU45y^wh1B!IOuTN-Xgp2%AzED4^9s!TD_HX>-zT#6?UY0nU42TTZha4xh!Ia)PrzB;*)LR7RcndIJaVtKETVuSq9R z=Y6uX=eVTHY``}WISvcUN0UAT@tevxqZ{P5}pQ%ji~n8y!v7@2ZMO-d-o-t`#5r+#Od)3ku@>Aox#4i} zCA+F=HDHpq{NLa9Kt-RKKAfuV#k)MMe3gW@v3c$hlXg()Lx7?J3oui1J>XxSR-WMS)noSX7oz!`o0q8tB2>!Ckg zI|~BWbqHd|K=jzTiB{Hd#|rj^;!tR1Wy)qtP+7udX}wLoyt35A*`*~>7jaqcM3vkL zrk>ww?lU`WQMh}!e$a;mG~u@`?wiRo&o;qBqV;hHfji6s?yE16FRkC zMJg<$>(97!s$6SA75yJ{w(hw937Q*K{r{NpM*6h#cwiVRUbhML4qh&N(iRe3tG-8m z<3GZEb7S;ZCZ)!(?hed9BjLJUqUA3ga&1YH?fZ6-xt7WnSW|V669tLI)2TCr>SmP7 z72($b1)4{LdY0hM98OX_U8?t>yQVi3T_0K1o(B#0O?o~I_!kwDK85xLSW87c4Vd_MtvUhL zRXUJ?U?pPiv-Sdvldnfbt#dx@?9bBI!%ETB%R8G0Cn`y39iRglXQ;&k>o;;A6zn{M zQppCq(n?D5Pye5cz8f+B$YdHhz`9XbS#~WZ9uY$PAI2C0t0*6 zlfzb0ICsKLhvGsbwZ=7s55v?6!m-7&mv8nOGhBA>Ha>CM9gjQIu-q?KJA7Q7 zW9j&l4sI_gu0EyZNHMN3`(|bx=BUkMKW@x!K(8!rYP<2Xm@?2w+wm%UEe{Vs-Lub96G??TKd^ooE!`H_UCEFd*2sY1p5tCs7$P@qG@Jkv=}b%H8I57T5g?PM z>M=_RjVU|RW!WEkIttl!p9H0qV*mn2!FwEzWS_h zEngV%2iKcOu+)t*(TuK^P9&)HwNm(ZB!-_#n&ZDh?nAgQy%sd6_7$i(^Vh^}jBi^F z_@UV$C_o{1Wy#WYcw<1~d1HxdQiwz{5%Lk=I<5|FeN9Y1^x_n1MA2s4Da9Kkm3e3jwO0LP<}#N&O71PXRU*BUZG|aGr63B zgPdP;M}1GxEc)lp-&lYow{Iqt{fFs~G@a7*X-2qd|xb1jq$(t$~}O10<&zD3Fg zQ&hig0=-W*0MA|g^4kXYsgR z@ zQ2~;##!nP>NxZWY9sMhKxdLTB+g6QD=IA-aLo*=Y%5l7AF=&_cgOMlFG# zbg8Ez^EdUU^W+ys9*nZ{waw;3p68}AN7F^1byD4NCQlUwQ`M5`813Tyd^E zN!Odlb+{Tu8E((r*`vgrDuHa2nOH=m+zur5;@ZDrUIzc-0j0gY=30}OQrzgQX3xCz z;VQbuneUQU_&kUy)yEN4sot7iEC_f~AZ~unkGTT}$R?(`CQLra7}1Md`z&UABYC-7 zV9@it#!%(@UN~JXz138GHAo_xBilMc86NN?9uO*F<|Qd6_dl|lMTJN*!3vWdSQ1@AoN~ndxh14#|=R};1KS-?{i~yc%+cR zPCIwNz2tPGH@J@b{buW=dJE!1Vj@%K=b^270C238&6b=j%192z=71O_gcE3em2=Ia zr;EykxtmK*?I&GE`-Jn=klsW*yCO;xf}GrN@IfAsvx*r8dY2iw)vfv-vaJ&O^uw=q zSf4T*BG$eW#jhS->@zk7>i_nronM!xKAFaelJon|E~;{dXKOZl!=IMk>W4}+17e2u z;fNvrv)I|GLl4!hhx^~Ih3;uaZ%+QW{M}Z%*~j(qVXkS|ncUA}%{!mP>^lyB?Dd$s zI=Q{GzYXgubxQq-Hd(vy$DC~0rDKLB;mUbqRxL5DIO`L%Kj59SW=q!3XIk))+CI3A z61GmSlr}GQIzF{&RXZOc%n?Bbz1F<7Jy%2hr@H4T@!Reb{5sWrUBR*lRL5B4{1tRV zDB9W+y5S0YYIAU#=C@pIpciH5FJ=U?^2$Jq>d(~a{t|G`x?w}uEmhl{>-v=W$cC)a zHE9ocQN1H!C%x^VLe0H5oq1Oo;#C)ne-utWG_kKflL(evQ>lu~wTf|1q>w8h0~k%I zHkINEsH?z-g!U%$-XgWRhykcL5{7)5(N^-)wOftD5l&%=gEEk?-jEcwo`)0tiazJG zajD}nlvYM~$(c*9&}WfOoIo|GTb3V7W3J3v>Z)brZm)TVVhu)UfIRfL4y0pa8(y-# z&+&B)6lE{rHTp8Ar`l%&%mSX2VA%$aYT0vqYVqtuceh^?8PVM$0TPx&#bw{3w3j8l zsN|o-d=oa7g*8xsg`?Zuxw--+R{A~XwP&0%&zETyJj)0pU%5OxU&LUURq%%6ycXvO zGD=qf|0lVF-t&T#!y$eadsL%uxj_@~KEa0gJilI^(~Be*1!0QOK$&Cwl!7BqhnITB zO%uhcaR+@O36ih6zRyDp_y?^8fjy6T3*MiVF(~!P+tEq(05T>4vsXj)6q+btE1U<`hN5i;gJ;t3DAn!E7$G)jx8PLu%H8buBEi+ zg&9x6M-3VQ)Dm-mxn|XDlv13V4#lg{R7)xYA1Lir;(gP~SA?y4^4COZ;MI*8{lxy@ zDsral?T}F)7Bd2#VVLJRZ|!NFr;sd+rAr1==wM@KTE))mSZPq*GQ00|M7a!IgVE=c z0h+>SWzF7`owk#l7cd{&`yMK4_y$vSr=O4Ib3TjV{rX_1>%JY;ecWhW<{3V8Q^5`t zn~9-2jzy|#tVmv|hl&O$k40(&TkGc2gBa}?s~_b{xiku4>>4fK-@8?r|AthjTy!A(oBKeAA5gXD!S5f!%1^W zp#jz$R5?|aF%(sE?B|f1PJrCjW$9$4u0$yfl^igjHy1s~N1%|b4|5WaaorFb$+j<4 z;*_8BuIp8gAF}*sL!{~d8<(||{eecz&i5+r4R!nwd z$0b%XPm(m?bXmAYFx+lEGkYbioGo8X)o!WRLWhA=>x)d)}k> zuTQPs!i5-@bd9h(E1W-z)pt4X*!i^4jT2^vpR_ZfIMH_%BNcxg_iU~(nvcks$#w-> z2o8?m5q0)uk|o_KX{-gL!j+TYv0;&RpP_YxCt@y9g(+M#hd%|yPTI9ZBn>=fsS)#i zb{8Hf)2}Yzai?t}L&x)k_XqJ@xDl{>q=ij)G7)eI#9K&<&CiPzMv71U5Em>4VJgZf^nq?rxLy@_+&WoJj;cNsHuB3X)MV*3E`tflU5hwxj zBIu1-F7^lFgYnB|_r!;uZ0|^f0F{7=Q%@GX#XpN3d)74&knzZDynF*lgH`@!Zi1;Z zUVgTRW_wT0PprU(G=Fdq%9j`Jr4FrAt75XQ^|BHS6+>yiPh?m0cD;#PEZb~g*=b2L zvECDh#a;6YOMLY~hUErO$#slNG^u5B!uGA#>Nawvz40b34c0zJkB)F}cWX$TM05ZW zvOR>Iehijr<^1(ertbejNp&R_d`WeuHUwx9{dmsd20cFb7E>u zc~fy{KlG|>>uE3cg3F?sH;pX=qOyg zyH?59#03?2uMV+PIJTFSfaR6?+=m^5uC(9?F*!oF40c|VUm!O-U}J|aX=Tx9k^fRdiglftJLjGs zfq&Yx?o)OhIU|j-A$h$sk?QNc*QWSY$t^I9F<-=@S9u{=ejR?Z*w%3fT~V>xn*Z?6_JE_K(|xLxt!e;M4c0q zIWbhv2Dvx|HL3b&n_-n5X0B|* zAssG*p(md^w2#ywyE1tCaC1pB9ujF|s}@fr`nXITZ?yKF{9--0rWEcL)!aFM`)$`t<{-C!$Hxm zVC9~?;U7zDLr!i>VAH6Z6Xd!|qlacZGZ=&`1Ag{KXCAG3VFxwuwLaSdPHCsr8|WN4 zl!@ZBdJB6XZ;-E_QIwkKD#Mg5y3-Bnd2Y;XZ>v}z*+w`!3iIn zpN+m5KT*107wx95^%@#oz0LnRA}r65+@lD7)@R#46!L8CGx8O)C%?RV@8EmArYz#pjfL*Z({os-je}dtMVwna9r0JU>_uK)Mutc= zEM;ckZL=fQqRhy|)vmlFp_Mp84STz-YvX#UzTxTq&t16uzU_QYCN;aqxo&b(+w!2E zTd&5kR=7=Sykiz_xR^)(fxt=s>Hm+->g%%^SD(hLX}06%Hd0f{zw@%zczmT#skTUk zWvioAXNWgRY8Lt^*uo1)jSf7awXp}{^1*cRhGrj?pC5{1m5-!$By3~+C0f4UX)DpP z2*rd(Pu)G2+qmnTgUsyMD0p&+Yl~xBgN}qe7*?Gc#^pcn8S{#MV(R%GcgJ&I$6h9;8xG2~^ivxfNjW0eEeJ4zJfgfQe5R7P@o=x$D=e%f`W53!po=i|1j zK~pkStPrn7=59`w=>_eeOgSWuz2|jci^`Lo*6Fs8bSm0IX^{N-+K|5tsv35$u_dl| zRF#rSe6&Vg1k=$hoBrejXw!?$(rX}OB<-#pQ|XEJB0)u`Enc)gle=Qt`fa7||ySGYeItDi;eLJ^lHg%x(XL zC=d|2p} zr7#ly_^DR)-CLg%fG0vH6K$OTA%0T`+xd3*}~`cjwKEm);a z6ku4T;pzhHEf41vEOx=g&b8 zqKl898YDHXSTO{i8-*L1(ZBj*;YtRfsAL2@=qcykB=V#uji~?XRm)c|=!@lsH!!{M zU+qufHINa`v!Ttn>ylGkR4!9?0IQ^S6l%Y^UGTBns(F%a@*^4t<+Tf?$lt^yI+;xzeKdfkVLZE`U(5YS{|H=D--jFBlOjIcYUo#{LdbG(iY4-< zMj`rrR8({C8)GM+ekXNw&x_{7+m`ZcU9 z_RoePk$o#qFw`|{`bbi4jwN&WFg-E2ZA>G??e-e~k{PZ{?O>t^|EUzS+P389OD{Lu z!~|4a-!3Xiz0*JlND-!rG_t)7ds!8!$K<+jEAgXMjbjNEG{!G%6@K39)lv!{D)yl~ z)5_J#i#=1Rr41zpfg>l!fQ0b32`4Z-TztN0z1KNQ)!`Re_nVsq!8)K1QG z8qy+5F>Kz03aRH-cSxA!lb^+oocnH%+qUR^WvO%TWv11mzH(`%N?|0fnj?(OO&%_B zCY%ki+#mP^TdkQ`X7>BvQ0+q#LmsA+d!}#nCOPCUyU}iZU3f)ii2c_;8ioJcq$9QC zK&2q=>c?{)_14WpugzmM&VW+3t%U6i`$3r#Lx<}RJ@ob`SrwvFxbfkWrL@V*Ii-kz z6|G2Jq4(aQ?xg>x@wJ+biY5Tl;{sE-Be>-mbd=`PurlL-PO(7EvVkQb!Ub>VW|U{*JI8Qcel!U zn1cb)&uhpzh~h^-t@T@dr&S4Sq4EPe@0RjY?;hI4aZC|cMXrc9pT)igmf4af-}Q$J zcYs{4|Mly`wP#6sk>O~9gT^&=DyV${-utxTRd>Q?v5SPl*8>P;)Mqh@Mfnj054<)9 zc*y49zTI$r$~1sis*@Of{9!Xcr@QI~ z;#>p*0c5&-NCX0n5_3-^KEAoyo)gyg<<{B6IlsC|Ki&|zMoP1DIOJvVpRf7L_Xt!1 z>j^{V4e}1sM#DvNOY~j)ya~bFQU@t{NTrnkdPpEmRW|EujAmBP9K&-H2g7TGB?9f1 zK;JOH$pZ*Dx#@o+eT-Dj72q5DPEIUDc#fE#$2dDOU(LyyZEi9*+;@mr>C6mZ8eN{N z8X6e<{R;&Pnm5S2&ti2&`{Mt^n z8~*`pa3?2j#D(;#KrX)34+RaY;3vZXWZWx{Z^y4yd6s9?oRZ8PDiQo>e&;IrxE6zk zv{2PvFQkp|%ze(y*;MiiY)Tn;O8}0kqA|&$mbt&q`-YNDXfFEia(T7kPMV$jYk#?Wzb6=Z zIo_vfmUl|aSi~nm803r5IY}+ZiwpY~p1>wFqEnRASA|H^H#T*9n&$iSSXYw)M>&luM@Z^8NJwgyKA?fvg!lqHhZTTW6 zw?Ff8C6fJ1t6i?(9o36)HBOg|zZFu4~wCHQk?r&yQ6>B zNrirXR5j1)R%q2Y&?M8jXkd#qdfY%UWT_V;+vi_ai>}qIen`yuWtZunR4b?n2Gt=T zkf66K*;WIadmJrO5BR_`+2K=-;3}VStu-lAkhn+#B_sno7!TR((c1IDJ0at>6FWuM zxLG#`TO9Cpx>?F~O>>CqIXm8g!qG(M+_KzBjTzi?!ItG6tBbaQ@3*eC7N(Wk^o)0+ z_NpqwmvSp^jEAXuMCMAZ32k0-ng@28)jFv2=x%d?vSJ_l@{Y{vYJ83wQz}@+-2egA zY3+QW_lLtbUlhlBvm|N_1$}H^Z5Q;-vOPbdDO^#G9vGEt8yfn3@OpG^4hL~DK0fFC zF|S+W^|DTQE7*GU_$M% z+iMrq(vdh*0+pJeh09KD6!o2Hukw8wHFe+dK=-Wt?vT77KEnZ)HQ{Yv=kyqy!}G|! z_X;7h0@7=o9p}rneVS{gPFp_1<{FM4&<=TVT*5co3jsCqzLo-L-%Ej`FyQ5c^|-aw zk5XQhImOf6&Qv2&XHe>n9d_13!D*96MU4YHSTVy3y(4xCHszJ8Dd|?c(V&x;ygrn~ zZ+X_FH4PG;j6xQa$=m#zrrRaInp>aL=9(L9j7AabTjYFTDV>7&)ByU5_`pyt{!_?G_i7&7%!yyW zpSQQB8x>iT$aEw`fnCOSOXh5tl>AwzqI7fdL2C9>>x&wH{-de$zpXlVjuqX~IBD?# zP^KFDyMO3%0@P~{K)qho@Fov6t{wb`dfnzZ0>StGEvkQscFP>%v-~aywWXI2Jw?M@ zpBVa^i*#C4VF|s`w$DizKHJ|ZG+r&N9Z!3lgUWR>Z<)HQ{vl<)1D4KHUkeiVUj;dv zg{lA@iB%Fe_<=_y6Y7Jz@~k)X>(K1}yTc)Y32S+YOl6GT&ov%pJ`LrT;H>R+ zke$e^waR(D&yo{=q%vh9- zod>8WV;b|_OTUhwXcf`<0dmT%A6~&{lE6%sey!D)1^XO%+5EbM=XKVz!!ONE3Ofr9 z14N|9qPBqoKbozqxU*ONR^#*W76JW{SpXK|X<_710{MZZ>6Yvny+r*%$y>A6#WCvEHA zsyWa+BIC7UV+++i@+r*eiH*;f?p)lNr?GPAS-vnR5FxGu2`$c3X>A4j;r>Y<1aNMe zadR%5ndVx}&AV>cehrmQGuF&i64F;|pUeRsLLxiu2xt!CP~X?Qp$D z8*;7Mpk^DZPKZ77?djO2#+@9`D>S(TqXg*s6y)A*u(m`V>N?4d%Fz+`T;%O1t8C8N z(Y4{{u}}V@8v1U1nb_c<8KIfEMwq%h{dzQDsB_t5?7<6zKg(*zOS}ro3NyrEc7}=G zIlSqCH#Rg4+C&ggU1gzFR1-aZmoRMinW?URhf$Wqdz0&d69xNcIuX>DUWvW62l|2|-2C zjS#&k6JoheY!K6V8{jey#iR5jg17ur@hDZ6;c4)>Fx!N9(yKWX5(x#^jUe$9F~ zZ2#7x{ZXEU({F0v`NoEG!mgdDS3C-nP{^&Cd;D2!)YZYG_6AKt^V?k6xHh#cUQ;RPpmvI5BubtHdj_`|v-M6{Xph4ZP-a&fMdBdmEz^#d6o(3lFy|(t3R9= z*rSUS2QJl>30S=cMTv*x(%FUOqq$Bdi{PJEw=#jb;F@P0F#5Jin0W)AtZy`7e{?*J zgNqv81MgegX!VS`TI+js&Q5;HiLB22NA^t!w_jocXym_@Zd~KXHiO!m)hF36Ty4c-kn{w1`mV>Q1$NY zg8au`y(z`zMO7{U{`q`)#&~gA!OI347-SBmwZ;%vQnh-{5{89oPBEV`;>Il1^U-;- z+e`dInTICf_!CDjUU*L^dETG1&PU9JfMq?T1CSDEX5Iy;4ApPCZo;kTn`SxKO<i>__#E3_PIkMpcPX*fCsg#?nNW zj#TF;Qp!sT0W5?XPQ*LT9_Aib;3M2>kmQOK)>3x%vUQusODyy7ETYTD(WRrN#7nC$ zk{8qr?FuzV^wxmR8`gi%?=oAZ-&h~qb>&ut!m2J-w_NIZpto5D1W4arfK8R1{jhL5 zA3yPH#xwe^;cZyj->b^nD7BCu$>nMx8^!cf;WH%wyis!%7uqlucblA1wDyGj$g#&h zkxo&)APUP5i5wKIjwhDzo5iI9A(xtzR>Z`P-x-x#eTw=u0^QU>6(p(t`7&QoKzOY1{b0jjh8sFv>9ww$1ih#bwH{n#ze{Xc>c={6-?FB} zjH9xfy(D|UsjeOmOmgdg>ETF6HsBui$G*S@?^%s1jFDy<76SUTof35+J0$EZFScHF zd?4UlP;-`xcuf_9K9t>>H@w?W*SwTTYEE);xCH^2(NMozvuU&$93$#n>zzQ>xN0T^ zucU0};POUXU&+062rUc&xuQSKgfUy=5|zuuD-F5L{$Wdt{3N!4$-q0!9gfx|^ks^! z2VzDC70gTq0dZ}}&V|!8yz775UcPqBGTKLVXZ_WvEOZHXvOCsK_d~uvjS|NTw;HZ;uE5}MCS!APZ|6fb zh

}!9&;@u(4AJOuVh`RAA2K!1gk)D$~~%GY_FVsc-52HGT!HA@}Ep_b&Fg&%*}> zW+nQ|C@c)FMG|MAaOwPP#!{1EYz@*ek%l|p@hnG}<)#E;V&)L=a-IzoF#P(lV&lHQP5a*&R7CtzG6#p)VK%dqZT^9e;MvoPecW+iFi}cTvdl8XQdz3fT-kA3-JrOn1G@?^iaA&` z`FS@45~`x$U-8nL{iYDD4Rz%-`sRrh&8}67T3IIG_qsR zYgFTz!7D8+Z4X5@HCT6}pRXID`{9F-wTjW;!bBBIzlOhBZtwBV+c-4mNtvU}FWB|f zj5n0{Yw|$WVak5S;elM^AYStmllWHL(m*QxXcK2ibLknS)KAV#uuW!kAdnpvHa`dh zess@&Rlfz~c3{L-r?}Io6SBVeUX$O%Dur{0P1jS}!m52uO0bMp(Iv@`!vpV7<~pZm ze!ZgQ`waFD-aaBw1C{U^MN;(6DvSE(k-M>f3l4V)6#!U;;GWtK6q25P8w{e2G_OJ7%X( z-*CXboQ|k_)4gTU5%X$5*Hzxo&EL$X^oV4!>pjj!V0C9EU_zg5)eX#8Zr-@boWQEz z*?Vj#q`<^lDChji8lx&@-QMj~v^BKU8ty+v)rgOuu0q+B)s1+}cl{+MR+viuddCwH zUWf0Ja+4F}Tag#&r;-j>_IBYxR#KK)(nhN~-)ctp89gKp_L~@9aMd%lnM1i22Agn! zer$A{dQ9=?aBDc}06^VcCCeFSnX~-js2uJ2&1{=vEVPFvI_#b?>jRx<0YaJxx~Csw zf4=^u^H2X|7zTd!pW{{Zr2AuALlxQbC;Oc4Jlu>^XMfCyJ5{$1GzRY5rHWkP2PeJt z3Dv)aCK1FRPb{mvo~V#_UkWT19QC;by>g`cs0t{a;-NgGc3Q6%@++uE1Q4r@Rl+GL z1_jT79_t{*SGr2O@3VCMx8}hSkecxpdkCryu|ukgzg92cUA{KVQ19nt0t z@6Td>HNzWcq;?(KK7F$`%#LJVk2GLU-b~v~avpBTcYBXWw}jt$yfD=Fb-cu(ITW!ZhM-U$0*%wD?C-jCPmL`3!-N4#V)YuWvO39!A6LgL=!aY zZcV@CojvlHUptdM=66FaGdn-T83xv4wAs4PEz#2vu}GR<*Xc8d3xAx>iF&Y;N1YFXQ2eqVt0pkF@;x#DF~pp`&xy3;T!;dIQ0g{-My_RRVA1-<1r7h02Z zNM&uGE_D!#%Gzvd2AA&*`!aD$*3Dwdr|tLtS~o8ev608IF)vS z6jAWE5!QKF=_BHO>;Mwc4ea}n3ig5X*Y~0)5;vH%%j`@hkSH%TAO%N)WuZE75C{SB z%?6I?U(xM*SiF0$0DD!s>(YVKI996PWJGFA-N=I)yl#GwxM?0)-QSed$LqJeJE>@S z_T?)te7;?m85|iD7B4`_9?53YtF&|i@HER?Q3JuHJx*$Iceul~*!FRtNBpDSWi~o{ zCMj%j^v$Eyn?cbpL|AJA*>_>XcGJL4w(Ru^m@bp5Y+JZB&Z_W&hMmfb<93OfSxDu;uOGx z3LL6mnOQ#q#$&)RY8M^f>=|hKlh{98u#1K4Qf(reDt*3oBiP-Tifs*$KA5A_>bPQ~ z9#_)TSty!PU1@4rg7}K-(+VX09W8LGDgcb8%Xpj*9RS^U`&o?I=J)4vBw^LZ0s6lG zDzwbzQZ_|ID^SSb)6|m#vs;PHCra8*ln|+5Rsk`fsueyNb~4R+G&UQ9i_7jl&GVevJErmpsQlj%gf!i#Wf%rdu+0uAQ7dwff%u4BKB znl1|1URXMqD(tpKnPgHI02jXB_$P8LtqE;l$7l%?@NWo+citjje_4##<2-eoHn5IK zA3V%#PH@mz%Tkkg(7Aj0S6o>k)g!}DFg6N%_2wL|LmQxu)8uQfICoDLXkkH27Z@It}7;TAP;-2l7hoF@m+uCduv!y4pM6_SS^5@P0;`Qp5lyIbv0bJw;7 zRMlibi^H1`cvzM`gWXh4(}9IDc0SBh?U5J|k7Ss2r{5SgFxk7tpQH%~%W}0XjDm3A+m`;r z`QyJ3xc&dyNdF(F@@3NV!Xwso;bpT&kqbm-=tMRxyiSDiVOr2CZ+IZe6y>)Mq;+rM z`x@N+(ZaWU?m`(P_%bCZi5Sg^%XfhZ{ap*j`ygCh0co9#BLJzUe~I1RCu8Rwos27d zA<`eJW%%-+CY+O$i?2Ta{-a+gX$>m>ET(ce=&`}26z9aGH!F7SttJ)VQH^s?97`GQ zAPS@0PPGKo0{Sf0_7&s&(?(!*W9ihFImzL(Cq<_?PTn~YGJd?hF#iDwd3tEusZbR) z1~GAoT0C}=trr;+F^Q4z8aPi+V!Nl@_~CtRU5&Ro+0#5AYZ&VAb}-W``qPBu36|7ZD0u}3U-SK`Z1-KnAY(uuL zoMd`~zU-Xk-R+walf{$j$=LFDiPxfeE|NS+9!LtQZw6Tkx7uAk_TU<*7YMg-t!QS-^)F8zNkVpuSJzFGWa5gFH za*aQ|PW2@2?-XA%5AXV1oAXu-s2Adez%Fa?xyi5T#fq)w=8Lcem z*EKO<&EL|^X$sAipybgyeD7?W*kv;Pi6&fOdAr8Q!qK|-EYo@$UhujU*PW8Tk?mpI zGhB@EM=y_d(mjLV=hafN*S0Y}k-5_T7vKdhO#^jCK$2vHlOmM?I#h9=<>G~Y#Oy={ z5~ZYqNw-wV9)+lUIQheGa4qh`$Vx(A5pH5epPk3KqLH*gs^Pdh5|Al@2a~*u#bI z!S|4`?*0aJUS}x%75RF>N}YzQX}}8x^}zhXM%pR2EUtT72Gtz%~i4}%-p2b|>JH=r?-_3ksOj@il*MX-P+yR7b z6%ZAz`b6d4n9!x>Spg`Hxsn23B24kOmVB}wqU9{Uxy9-SUZ7_kS!hPO= zmF$FjLOS;PiLp1S*D34=G;g=?rc_3hL1fvHoUk4 z;~sa|&3V22QKbJdq3z1r`~qX~Uhz{W!KXUqQZu`o4p}J2^{8Oe7vINKjm>xX(C!8F zC*wya*IpnS?}j%#5a=@CBg zPvt>+LP#hzQ6(Hy^w@zv&@g#8^#^b4I)r2#a+W^t`PxoSa@$D(a>k+v7Mj7+K}F44 zTTobrEaI;V``nb=Z!*hF@ms5g?sJm=qrEGSYUQ+Rg2owc11&kEJ9+oO# zWEWxx1Ok?wM0N-mwy6qAP%I*W009Nr0s&c)NWwCr>;Z%jwy?+!fe--`KwRc^rgMJ3 zLq-4I{!tSk#JOuEJA

=Jy`7>ynaBqqssoq?l$q~k_igRir|Zu2PHWhm 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 literal 0 HcmV?d00001 diff --git a/docs/images/SDP_Logo_VicGov_RGB.jpg b/docs/images/SDP_Logo_VicGov_RGB.jpg new file mode 100644 index 0000000000000000000000000000000000000000..81d21b0f4228c8336001bb0ec6bad39f6cbe1221 GIT binary patch literal 381014 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
9AEELMnDT$9f_iQi4C``H_{gb@-kHL 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Ò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
g_FXId~C=VkYp9CBba)Tw{i?(X#d_ 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

Swon?gvl*q@KXj@+oV6LTH5Ad}a-2waH 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 V2@u=|-)(h6QC3Z+O!{^3{{bT=m?r=L literal 0 HcmV?d00001 diff --git a/docs/images/bb_webhook_1.png b/docs/images/bb_webhook_1.png deleted file mode 100644 index 23dea3aded0d8c5e08e0e1e3f31100766b3de168..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35575 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 diff --git a/docs/images/first_deployment_slack_start.jpg b/docs/images/first_deployment_slack_start.jpg deleted file mode 100644 index 2aed71ec802818216c139f4c28def21f5beaa1e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5853 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%0AETOnADx64 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 Ac>n+a diff --git a/docs/images/gl_webhook_1.png b/docs/images/gl_webhook_1.png deleted file mode 100644 index 0a6eceb190f5430ad0a3d555421c2a41590abdc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48384 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 diff --git a/docs/images/pod_search_domains.jpg b/docs/images/pod_search_domains.jpg deleted file mode 100644 index 545278f09d28252c1635560c1874b3445c8a5bb7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181907 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­WcXGYIamz zMD?UUycCG9cGk;u+K?xDkynR(?Big#*)dcShmSFYLFHIWJ~c4H zVUxxS7FnffRJfNzR?bLLL|io<97!SOiLh)&r&WoCINH8DwzmqxT%*nk(TvNh=as3{ zakMQ=3v|aC5v6?r8-wym-kpGqgBTHtbf4t-x~H*hO3wxFi|2L6YL@Gzll8dg?!K}w zskOI-0H%{YU1T$V=1ZsEzb3K4MP*j0Z*zZY*Eof*LQ%GL?k;?K-hvlH?qq|M>Gn+l zfC`)~UizK_)U#0?e#<&BYlhAI$u+%-{#WD zWB8i2#3}>6ya5ZTVo4oJMWd<7Y`9t)DjjVyU%e3nio}w6-th%C(U|_#>gYy@NPj#M zqV?^HTk7oCH@@H~Pa^=)AWN0xeuBOn7@e!X?VX@@)v(x_e0MGDz z;+M;wX$%g9G^w&YS*U#0Y09n8X!vfk_^wK4dZ9x5p~+TA<9{)<+?$4%F>(Mn{G-pg z!k=04fR0_1^4v8Z0*dJs&jZ0>^#(lGr6Zl|1i0c_oXrcFJJgBDPKU{EWFdy ztN;o4nZ2YFvh+?tmsN}AO?##&UY7}LdT|V-r&ID+d&oj(ypve;WsMm_!<343p9H}v z(wR4gdN28662p_mr4oK0K9<71?BaWYlyOONRQV3AJaP!V)cNWva>!wJ&a;y(e1g_0 z+_M`kLNQtqRF{kxn;~C5pY(MHGM4NX>KU>-L!b6WpNdD@BNLgBN_+N%NtETOh#g{; zEdxD@$=)!hwM4~0?EIRZWxuSHyS+_N)B?085fy#xVzlCCUY9g!GW$XdQS3me$jWoU zK`94!B|rO~ba~jmV$rm!>@yBH0ZY(3qupO_{ZQI!hLZLcyMeRi=3F=9{CL=>;3_n& zp^bDE@B);YiCzw-EMZQs$|X*}6tPFS2+*g1btOV^(Y$gUxlj!96xn@4mS0IZx5H_% z2wVL+gv`9Z12mxzVb0^p$h6PgQXfrFYMpRynfL-J>Kv8{1*ezM)!gJCK!274zW4PQ z132nh3~NqJi7J;yWgVS`5YuE?Ic>z4;wU)UGl>%BPSASw-O1L{k3gVfcf7%Cd;Z&? zJ+I=#&Ax{GFphKJcKNMx#yM3AIhGQhKMFWY9WaNYturkQPgeE=_jIr@$0%Q0gl`4K z$K?V+-%-_J#QqFN@-QcUR%I!CK@W02jsF`HW3Fad<39!l`6DLAqtuh;Gtxm}l2);& z`;y9~s?ez$bCnEP9XVEGvk1C_=CWIAP0#vMkop>$R$(pnhxRDXC^y()V@TX?){6j? zz92K^pi{KAv5eFes8w7!1hy1H;W;wg?(>eu5Mym_mBCJ<^S$n4vLHuDYr z=iwg!i*qE-DTGO6B@DVdu^)g(&6j6CSic_t(6Y|vOC=&MyVXp=|EpLVk3v6P7uGxw ztUAz%CZtat=(i!BN>?m3b%uG$D1!?-se!7xhudNMel@UII~|}^`idtR?2~{(&7EXqCm{o!4$<^jDZ`!j9nG5I$z4U?NI zhj?MTggJk&z{uc%G`ME1xD9rryH0&}*$Ut+H_l2>;bOujkQiTM1;6@j(X@iAuHgC+ z99`IvagOsIX?EfY1|l7kl8|T|PZhczy;;QwiV*h|77sgTFFjZ`9FNrK2=S*;ZUFL2 zeiC0OY4a!~+8K&mW}}?5Gqu)^suuB8qRZR8g)~0{UTEJj?8g%RaTO;jf0jgiBZ2~Q z)E(|4(li(TkxKp#nau+};1YI4?|p(2KU39L@-5zTI!R8xukRPEO_(-FF-9&UM$kTYC8gFZrfZVBuI8GAu zwgO)#T7Z>C!N_!&BqHRyps6I#!g*!d!^_WA?5{t4(9jip+`ijsXz5%ce6CnDcRu^d zF}G0@_pWJf)Ae1|Fh-Vf^MlRfM@fP0)pdnSv99J_9tW0H)rLwI;H4MZkn?HUus)yp z>e(sBsE=*gYYR)?3@0_z+0ZsNba3^4r$V*qj^LUhvb*`WP|a&F+3B%|6dx#5LLS$a`1YX*#O87W_UmyahU&05xq!r8;WtOFid{erG*8fOrUcBi8eZqn~+)L@Rr)I{!dSY93+V=>hP>c zxopVXRVq~zVQvX|%hPA9nT9u>A7G~g;XlfdpB-|%d0D+l%mKI&#pBT8OTGBvx$uajlq?0dV&hhTB&hi$xr<{Pv-0g;P40F3&l$} zXkz16PXT$4!No^c%F;cOAFOQ%?mMQ6ZVZ(|11<_f51dky%9l`0H!{d6NGPA%jEWKe*hzj+UTcFJ)ouGt4U$zu9aaqp*ZIR0>Q zB_(N^LY4ka^V$#JyJES7T+{)z2MkkXR!FW@`aD9|{RWnw%5efpf1Fpzagb6N493|| zo$D11rMMUJ1|2h0+f!go=E=HoOiM#W`~=T@GC<8(<6*(Us2?JIvp}#yjd^3)GywWq z`JRw@?a)K`MfPux4#R7qY9b@Q@%cx#O9elv%i(gz8+*f~aI{HUh?)B`XO7Mq^q{FQ z=wz5kG;7mb{F)Vsck+hOHs81A;O$#l;?7zSXs4BDEz@`4GswqMFKNcP^Kp_8@q^N3 z@Z6XyzBDzZ&N8GrXN~jkIoJ_VXd51D&Y9^>lBFT^SUSKn*BD~#^pY52(?jpyN=Ut1 z(Q}gACN^hHGlzlv$d6k)zgCNRj>TGGgLdC#(J>k+vqOs6P>J2`{o@n7e&L;hHy}D zJ|~0uD8?5bSS}+Ib~9ngIH!;UWAE|OJx|6}7joDl7!wsrrH_|GWjhk}Y0t!PVhs)9 z7v}4%HD;Y=sox#*rxa{{R$w!M@fy`euA_1_%B=esc(7;<+*@mJ@2;b1%-vJ^$IIge z=BZ1mK?r^6=YO|&U~$E~v+R)8hV{bMNm3XhHyVI_D_u-<8V~=zj~CanW;E(DMkXCi z9sw`{c`DM;>gp<(mZ7yvzKz>uVoklf{ubiWYU??%>0SiX(aCAND>L*D+R@w_yc-Hf z>n&o5-b&ifm*GgV=S&?O=454U{G73fjNW-!%ZLIFM8-rOnrDhaie`PVlhly+Qsb(Mf8(W#HXR@ z$)q<4=5=@vx5Bq%O5hN68h|miwu`=tV#G9*OexqOku$BbP+UYR@14bff zMrTNIlWww>fuy$6t(uXqm*i*fvg+_8VZ+#11=w8CUxBVCZ@S_62z#$=^prD}v&=3I79~b}}0u`u& zMk0cO&Z7F7n3Pr28IqYz+1P|k*vQExKup{}e&*ssUhR(+04x|d7?=<^D6D(qqC6T8 z6??O;9u4`sF-|SV>^^JTtf6t@04C(}k=AB^ZfVjjA~dD)w@#J$sy8e|M>{UrTkB_|3v*KD`_ASOcjIV z-yJAcze+T2{G39E3rqHq6ssHv1yu@Z z@maZm74E#u`X7K`_Eobt%jMns?|ZpeQLWWdWN5|nVbzkgbHq$NPpitC*RcTQu$?k$ z6dcMTJvRUf%n>LVwPYBaW$460waC0hag;JnwZtI#z3@bQcPv2W+3BcAPx(qv=WE&z z<-klNm_Wv)ka#EB<`iAgN=4}l1xC(gw1M~iM&?7|>?x#WB$&5_7!=awvW3e4*#xy@ z9nr#ag?PwvkU_MIav5CC1LJDsxO1s~;^r!8kZ+ZEob~Wsu1KgtC%g)?<+E5H%px#& z-?}J4d)?@Wz%8iXd=Sw;Y1n4>%x)IZHSf@Q(eFfiE8z&e9<=V_mn6Mh;i_ydSJ7#}@4ap7Hs5=@SNP%D1tkutEjHjay_ra) zq7)-~CQ=S^qQ=hE3poy5aGF3{wiI^jjj$BFbWb`J$3}y}7}Td1h|mu@JKw1C;xKVv z>q{_OC-UIOU6)WD+9&YqQYEJ-W*r2rp-)-y$E0*{=$7#0@2L1hR*jWd=3?k}e`o9= zC*AQ(hQmiCzr3gO^eKK3&I#+oiZQT!rG74>}0ev5Sv zi!!cf=AxQ$78s?sL85$mrN)1+fp@RGbsBFP2M8w~ldjuROcu^7xqiMeG~R6(KVzz` zlC57@b{Y2@V^J%yFkwf!2Fe3p=I5i{K;Luq-X%MJ{t|yaIUXZ&KnZc^gM}J2z zwJtwqCz%FZIlWTcM`(OCb^dWRqv;6?P8Lx16)5%U-_D%h+xm;rUrFo>v z-AbeUi~5`K+AsAdV~=kkh`*EOADOJ_DQOIl8AonsUw@?d& zEy~zZOW9R7_o5ILQ$v)G$7I7mF=u&Q5*dEB>EsS3-q(8NOGv>Qkd!xB4?F+qY%k$1`X#AT@w?$R z@?L9Qz1?21AC_1m5#mN3Uq2$>li3;bGkCEDN%F)U6F-yEJmzxV)1_PgyWA7zK`SlL z%mb>9pE_0}y^49{Ji?1oufYCjt;}v>ul<-CklP~tYGL?LV>y5RvBSOUKCN3gvu{6` zF`5qJ{VUsYBFgA9FcHTLEU@aHtv4#~50v#wrrb1E%QSDBpH?R_U*oB)NW)E*QsVIK z&Ac^d>qD1RKdEplQ(jgo_X{pHV0p-70(`ij{eY0bsy!g25PM0KBuTK3Fj-E+4_yJ% z@m)D$%S{C#^F!?IiPc98*h{$6iiKCXiQu~YiuY`*$_mcLBE4&zSkRY>&R+8NWZ${a zMT`|d(`_HUpy1k{a+rZRW7!k#B38*i0BZc;oN8an67&4^ufjKo&g)?MpP#lbeL{sF zN(3cUGepU(%Q(JW#b@4Y@;@HPOeY67)Z6w4Jdj|P$rS67@}~9gmZO3p&FU#fvGNrv z1+uUavu9ApF_`txR9A>{ioe5yPo}LMloIkNX>V!gM>fHV+K0;P6$t6T?%M-c#ovDn zUkH(awz?%%)J7?F4t;9P80GlxCHo=pFd$ok+oOMkHPOf}n=;`fFM_24F84ZrSr9!` z)T%MduLg?siA84QAeSZs2F4c^iTPu_JR3gjXHfj`=tZlwX_K)>r0nchc!J><)b=yl z1e}Oz8d4K+X$u6LAMqRT02D0A4^I`4O2_xvf~F)N?$Pq518v3pR6eqETZrd6lu>UIcDn!mpw5T&rbwjz#k@`OY&972F{|`m~v&1TtoZT<;e}_PXQJH;U5y&8@ z$Unfp6TiUUrPr!8_p1J3;urb5YQIc?D*F#0i2UOO{$A!EX8$w-0{>nn=)_Ybtoq$$ zk^3F@x^nw`-|4^D`4NO@>uVG8xxpBTS=8$=NacS@DLvKJyLm&W+K9(Nr=GW3a?_|2 zJ9x9MZR3NBtZrW2pFd|&Vzh&zsiC>-(0f${zM!pbU3q?!6tGiK?R0++tg5XdYD!utvRGW!2#h}l$bSAl)dR=8h%=(v2>ZNa(S zrgfb|&mps#OF@zAL^B2a@NZHqK|> z-%BgJt;q5HMt(RZs=dsy-SdnRrB*n{kU$`}eYpVZA7;%+Es;SmOVx{=5sxdMER|Ys zgubMnhes-e7&3;TWm1rP%K5+Gu{-eVv3oiY(mlV>f%P1}U}yyDHMQt4_!;|w##~~* z#$4dA;4m-{;80M%$6S!;C}<=sBC2W$#H^%jqRPh30nEZ;uZ>Jy$k?5r;>G;~^Xf3j zO+NfF^n&xQQXPvhe-cM0p^JY=sn_cR|3OPM<7sy*_2to`r*^FvHSgv zf;IEDT~;f#ONmihRNzi^byfa~eL?uer5^jb?)QP<-cKZrIHTBhlrB2WBk;r!;$dI# zo>OI>YO>L~km67wi55 zxwI+qTk;>Zu-bM1BKpq_{N^gJ>2c=&rR;yS_y_$jYE$*siv6;SIN0wH>F;EBldQKm zX6YAF$SqH5UWl?SgjqYl3JC?oAe;@ATb1uo$JV8U6`oL1Ld2T!<K+}-{Q`{fc(U!xc-4%MNSZll2W=*4VP5|X?w>~ONksz@G_oB`jAc98YaB|pUpG!#n*ojRt|CY;P zI@0bK!%;ynnDgrcL(%)^HZo2u=|?vCni;-#e9B09^=+TiMI5Fd@APKp8YwZM^#@UO z-18)W;0`2QrowlguevwayZFY`4u$dN-cF0(H`k0wO`Inh9=a|Y&%j2`xUD z4f&dzh*u~}=)q+4^s|lgB__?%8vP=#YNw9Bl216i23oZ$TqQ7+Di)t6re~yQK5@yO z_>h#L7%1*h3a3AmDI{X)a>{gQ7Lgfz1vQ1**W(SKCOLcn|0Sm#m21&BxPSIBnKzmS|zw@ zQ+(~%>#SULyGgX{RWiaid%sVrYZ1T^5etjjY+`${PFMC&2xf0~CT4XVwjk?tV<=9< zv?LyUP-^F&I-s>gD>)rVZ`*vd&|on+t}!aBi(;x1%o#JTu^{Gdw^nN3I^848_sLeb zl@x3P#mZs(Ow;j^>g>@UNVQuS==mJf;yZ?w!sq87G2Vkm^ISw_7kdqvbnDxPmG*qi z{aDz}>?&2zq?o`JpLx^atTSYHoe#m+4q{Mp`N58$we3%NfC z?N81{i+6Oo-X;yMuz+~o?6}dSJPbv`>L=`K)qMxrnOq>hXWpeA`P5uqXPCO6L3g!M zKKM>oU8`o?rUK*MUfradp}bOazv)kr`C$`U3}&#GFD)}}?9LjOhI>`J%~2m(t#+^w z@!1W9XUyN&^TPygz+1I^M&t+Ic_$YdWxdsU=lE^L+?OAV2nLZ$L-WG$aO-0fU4`G+ z?wSSe`o7vtf?ABLgmx2Vol{XYQFpTZ%u z^xWes>^YQ77CB#Mf<8YLsMtw4RwEbdzl08QH_dULWir`%WS2MlBP`av=RDUr@=*68 z_b9*!ie$7x%XEDP*YPtHnh9UJNKVQk#SHzr%1*fWk$yhhj;&R`DtVCPyEn~-mLGHe zL(5Z=Hc97Md!>!}(8$BEAJowt!h%eZnqT3q!%B|M#i%Rw>UPEmr0#1{)rUxXMpvOS z9?FN--0zfLcvproKLDb9q#qrNZ4#bQJLOBfNBl_Ne<6KF<1&6J%Z+%7L`pJ-8Fv}_-jmpK>=;b&r@Nfol zf|rNxRm1bUEcq^IU)hkb2s}slyZ}e6e)3WBR-3~BoP->u(|X5i

wWa8D_`Ok|}=%*S`k9w<> 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Ν^o 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 diff --git a/docs/images/prometheus-kube-state-metrics.png b/docs/images/prometheus-kube-state-metrics.png deleted file mode 100644 index 198b9153d5a830b774f221c68918aed38f57b53e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32760 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�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 diff --git a/docs/images/prometheus-server.png b/docs/images/prometheus-server.png deleted file mode 100644 index 8e944d7cbfd809a4bb3a58dca6f04e84dd24ad14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53782 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 - -1. This `ConfigMap` contains the Grafana configuration, as defined by the Helm Chart. -2. This `ConfigMap` contains the default Grafana dashboards, as defined by the Helm Chart. -3. This `PersistentVolume` contains the read/write data directory for Grafana. It is used to persist configuration changes and new dashboards. -4. This `Secret` contains the Grafana admin user password. -5. This `Service` is defined as a Cluster IP (CIP). -6. An OpenShift `Route` is used to make Grafana visible externally. - - -## Prometheus - -**Server** - -Prometheus Server is defined as a `Deployment`. - -placeholder - -1. The `ConfigMap` contains the Prometheus configuration, as defined by the Helm Chart. - a. The `server-configmap-reload` container watches for changes to the configuration files. - b. If a change is detected then an API method is called on the `server` container to trigger a configration reload. -2. This `PersistentVolume` contains the collected metrics. -3. There is no `Route` attached to this `Service` as Prometheus does not provide authentication. - - -**Node Exporter** - -Node Exporter is defined as a `DaemonSet`. It is responsible fofr retrieving metrics from the node it is deployed to. - -placeholder - -1. The `node-exporter` `DaemonSet` is configured with a node selector of `region: node`. This ensures that it only runs on worker nodes. -2. This `Service` is defined as a Headless Service (HS), i.e. a Cluster IP with a definition of `None`. The `Service` is used by Prometheus to discover the `EndPoints` to scrape from. - - -**Kube State Metrics** - -Kube State Metrics is deployed as a `Deployment`. It is responsible for retrieving metrics from the Kubernetes API. - -placeholder - -1. This `Service` is defined as a Headless Service (HS), i.e. a Cluster IP with a definition of `None`. The `Service` is used by Prometheus to discover the `EndPoints` to scrape from. \ No newline at end of file diff --git a/docs/metrics_charts.md b/docs/metrics_charts.md deleted file mode 100644 index 3b02a113d..000000000 --- a/docs/metrics_charts.md +++ /dev/null @@ -1,74 +0,0 @@ -# Metrics Charts - ---- - -This document describes the Helm Charts that are used in the Metrics solution. - ---- - - -## Prometheus - -The Prometheus Helm Chart can be found in the `charts/prometheus-dpc/` directory. It was created by taking a copy of the standard Prometheus Helm [Chart](https://github.com/kubernetes/charts/tree/master/stable/prometheus) and then modifying it. - -### Modifications - -1. An `openshift` key with a default value of `false` was added to the [`values.yaml`](../charts/prometheus-dpc/values.yaml) file. -2. A [`templates/server-route.yaml`](../charts/prometheus-dpc/templates/server-route.yaml) file was added. This creates an OpenShift `Route` resource for the Prometheus server that is used in place of a Kubernetes `Ingress` resource. For this to occur the `openshift` key must be set to `true`. - - - -## Grafana - -The Grafana Helm Chart can be found in the `charts/grafana-dpc/` directory. It was created by taking a copy of the standard Grafana Helm [Chart](https://github.com/kubernetes/charts/tree/master/stable/grafana) and then modifying it. - -### Modifications - -1. An `openshift` key with a default value of `false` was added to the [`values.yaml`](../charts/grafana-dpc/values.yaml) file. -2. A [`templates/route.yaml`](../charts/grafana-dpc/templates/route.yaml) file was added. This creates an OpenShift `Route` resource that is used in place of a Kubernetes `Ingress` resource. For this to occur the `openshift` key must be set to `true`. -3. A [`job-notify.yaml`](../charts/grafana-dpc/templates/job-notify.yaml) file was added. This creates a `Job` that configures a notification channel. The `server.setNotificationChannel` key in [`values.yaml`](../charts/grafana-dpc/values.yaml) is used to store the notification channel settings. -4. Oauth integration was enabled. This was done by: - a. Added a `server.setGenericOauth` key in [`values.yaml`](../charts/grafana-dpc/values.yaml) to store the Oauth settings. - b. Extending the container environment variables in the [`templates/deployment.yaml`](../charts/grafana-dpc/templates/deployment.yaml) file. - c. Creating a [`manifests/secret-oauth.yaml`](../charts/grafana-dpc/templates/secret-oauth.yaml) file that defines a `Secret` resource which contains the Oauth Client ID and the Oauth Secret. - -The additions to the [`templates/deployment.yaml`](../charts/grafana-dpc/templates/deployment.yaml) file can be seen below. - -``` -... -... - {{- if .Values.server.setGenericOauth.enabled }} - - name: GF_AUTH_GENERIC_OAUTH_ENABLED - value: "true" - - name: GF_AUTH_GENERIC_OAUTH_CLIENT_ID - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }}-oauth - key: client-id - - name: GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: {{ template "grafana.server.fullname" . }}-oauth - key: client-secret - - name: GF_AUTH_GENERIC_OAUTH_SCOPES - value: {{ .Values.server.setGenericOauth.scopes | quote }} - - name: GF_AUTH_GENERIC_OAUTH_AUTH_URL - value: {{ .Values.server.setGenericOauth.authUrl | quote }} - - name: GF_AUTH_GENERIC_OAUTH_TOKEN_URL - value: {{ .Values.server.setGenericOauth.tokenUrl | quote }} - - name: GF_AUTH_GENERIC_OAUTH_API_URL - value: {{ .Values.server.setGenericOauth.apiUrl | quote }} - # TODO: What about allowedDomains? - - name: GF_AUTH_GENERIC_OAUTH_ALLOWSIGNUP - value: {{ .Values.server.setGenericOauth.allowSignUp | quote }} - {{- end }} - # The following values are so that Oauth works correctly. - # But they can be used for other reasons as well. - # TODO: Might need to put a check that the value exists? - - name: GF_SERVER_DOMAIN - value: {{ .Values.server.serverDomain | quote }} - - name: GF_SERVER_ROOT_URL - value: {{ .Values.server.serverRootUrl | quote }} -... -... -``` \ No newline at end of file diff --git a/docs/metrics_dashboards.md b/docs/metrics_dashboards.md deleted file mode 100644 index 44306ba27..000000000 --- a/docs/metrics_dashboards.md +++ /dev/null @@ -1,260 +0,0 @@ -# Metrics Dashboards - ---- - -This document describes the Grafana dashboards that have been setup as part of the Metrics solution. - - -[PromQL](https://prometheus.io/docs/prometheus/1.8/querying/basics/), the Prometheus query language, is used by the dashboard widgets to query the Prometheus stored metrics. - -Currently Grafana [alert rules](http://docs.grafana.org/alerting/rules/) are only supported by the graph panel. This will be added to by the Singlestat and Table panels in a future release. - -**Notes** - -* Due to a bug in Grafana the dashboards are currently displayed twice in the dashboard selection drop-down list. - ---- - - -## Dashboards - -Each dashboard is stored as a JSON file inside the `dashboards/in-use/` directory. The contents of these files are then loaded into a Kubernetes `ConfigMap` so that the dashboards are automatically available in Grafana. The `ConfigMap` is populated from the `serverDashboardFiles` key in the `charts-values/grafana/values.yaml` configuration file. - - -### Alerts - -`alerts.json` - -Alerts dashboard. - -Available alerts. - -* Cluster memory used. - - -### Kubernetes Capacity Planning - -`kubernetes-capacity-planning.json` - -Aggregated cluster wide metrics for both the nodes and the Kubernetes system. - -Available metrics. - -* Idle CPU -* System Load -* Memory Usage -* Disk I/O -* Disk Space Usage -* Network Received -* Network Transmitted -* Cluster Pod Utilization - - - -### Kubernetes Control Plane Status - -`kubernetes-control-plane-status.json` - -Cluster health of API servers and nodes. - -Available metrics. - -* Percentage of API servers that are up. -* Percentage of Nodes that are up. -* List of nodes that are up. - - -### Kubernetes Deployments - -`kubernetes-deployments.json` - -Aggregated metrics of Kubernetes `Deployments`. - -Available metrics. - -* CPU Millicores -* Memory -* Network -* Desired Replicas -* Available Replicas -* Observed Generation (how many times deployed) -* Metadata Generation -* Replicas - - -### Kubernetes Pods - -`kubernetes-pods.json` - -Detailed metrics for each Kubernetes `Pod`. - -Available metrics. - -* Pod Status -* IP -* Ready -* Scheduled -* Average CPU -* Current Memory -* Average Network -* Average Disk I/O -* Pod NW Transmit -* Pod NW Receive -* Number of Containers Running -* Number of Container Restarts -* Number of Containers Ready -* Number of Containers Terminated -* Number of Containers Waiting -* Container Memory Usage -* Container CPU Usage Seconds -* Container Disk Write -* Container Disk Read - - -### Kubernetes Resource Requests - -`kubernetes-resource-requests.json` - -Available and requested CPU and Memory for Kubernetes workloads. - -* CPU Cores Available -* CPU Cores Requested -* Memory Available -* Memory Requested - - -### Kubernetes StatefulSets - -`kubernetes-statefulsets.json` - -Similar to the Deployments dashboard but this time for `StatefulSets`. - -* CPU Millicores -* Memory -* Network -* Desired Replicas -* Available Replicas -* Observed Generation (how many times deployed) -* Metadata Generation -* Replicas - - -### Nodes - -`nodes.json` - -General metrics for each node. - -* Idle CPU -* System Load -* Memory Usage -* Disk I/O -* Disk Space Usage -* Network Received -* Network Transmitted - - -### System - -`system.json` - -Detailed metrics for each node. - -* System Uptime -* Virtual CPUs -* RAM Available (actual) -* Memory Available (percentage) -* Disk Space Usage -* CPU Usage -* Load Average -* Memory -* Memory Distribution -* Forks -* Processes -* Context Switches -* Interrupts -* Network Traffic -* Network Utilization Hourly -* Swap -* Swap Activity -* I/O Activity - - - -## Development - -### Workflow - -A workflow for further development of the current dashboards is as follows: - -* Inside Grafana, create a copy of the dashboard to be developed. -* Make modifications. -* When happy, export the dashboard to JSON and overwrite the current version of the dashboard in the `dashboards/in-use/` directory. -* Test by replacing the current `ConfigMap` of Grafana dashboards with a new `ConfigMap` generated from the files that are stored in the `dashboards/in-use/` directory. The instructions for how to do this are below in *Generate ConfigMap*. Check inside Grafana that everything works as expected. -* Copy the contents of the `data` key in the new `ConfigMap` into the `serverDashboardFiles` key in `charts-values/grafana/values.yaml`. The instructions for how to do this are below in *Update Chart Values*. -* Redeploy Grafana and test that everything works as expected. -* Delete the copy of the dashboard that was used for development. - - -### Generate ConfigMap - -Once you have saved an updated dashboard as a JSON file in the `dashboards/in-use/` directory you can redeploy the dashboard `ConfigMap`. - -First, delete the current `ConfigMap`. - -```console -$ oc delete configmap grafana-dpc-grafana-dashs -n metrics -``` - -Then generate a new `ConfigMap`, using the files in the `dashboards/in-use/` directory as the source. - -```console -$ oc create configmap grafana-dpc-grafana-dashs \ - --from-file dashboards/in-use/ -o json --dry-run -n metrics \ - | sed 's/${DS_PROMETHEUS}/prometheus/g' | k create -n metrics -f - -``` - - -### Update Chart Values - -Once you are satisfied that the JSON files in the `dashboards/in-use/` directory are correct you can update the Grafana Helm Chart `values.yaml` file. - -Create a new `ConfigMap` to be the source of the changes. - -```console -$ k create configmap grafana-dpc-grafana-dashs \ - --from-file dashboards/in-use/ -o yaml --dry-run \ - | sed 's/${DS_PROMETHEUS}/prometheus/g' > ~/dashboards-configmap.yaml -``` - -Now copy the contents of the `data` key, i.e. - -```console -... -... -data: - alerts.json:|- <- copy - { <- copy - "__inputs": [ <- copy -... -... -``` - -Edit the `charts-values/grafana/values.yaml` file and replace the contents of the `serverDashboardFiles` key with the content copied from the previous step, i.e. - -```console -... -... -serverDashboardFiles: - alerts.json: |- <- replace - { <- replace - "__inputs": [ <- replace -... -... -``` - - - - - - diff --git a/docs/metrics_install.md b/docs/metrics_install.md deleted file mode 100644 index 08ba4bf90..000000000 --- a/docs/metrics_install.md +++ /dev/null @@ -1,179 +0,0 @@ -# Metrics Install - ---- - -This document describes how to install the Metrics solution inside an OpenShift cluster. The Metrics solution uses the [Prometheus](https://prometheus.io) and [Grafana](https://grafana.com) products. - -**Notes** - -* Ensure that Helm has been installed into the cluster, as per this [guide](helm.md). -* To execute these instructions you must be logged into OpenShift as a cluster administrator -```console -$ oc login -u system:admin -``` ---- - -## Metrics Project - -Create a `metrics` project for the workloads to be deployed into. - -```console -$ oc new-project metrics -``` - -Give Helm the ability to deploy to the project. - -```console -$ oc policy add-role-to-user edit "system:serviceaccount:${TILLER_NAMESPACE}:tiller" -``` - - - -## Prometheus - -There is a [customised](metrics_charts.md#prometheus) version of the standard Prometheus Helm [Chart](https://github.com/kubernetes/charts/tree/master/stable/prometheus) available in the `charts/prometheus-dpc/` directory. - -For Helm to be able to deploy the `NodeExporter` `DaemonSet` into an OpenShift cluster, the `tiller` service account needs appropriate permissions. A shortcut, until the correct permissions are known, is to apply the `cluster-admin` role to the `tiller` service account. - -```console -$ oc adm policy add-cluster-role-to-user cluster-admin system:serviceaccount:tiller:tiller -``` - -**Notes** - -* If deploying this to a local MiniShift cluster then you can get the IP addess using `minishift ip`. -* This example uses a local MiniShift cluster IP address for the `server.ingress.hosts[0]` value. - - -**Install** -```console -# Get the MiniShift IP to use in the FQDN of the route -$ export MINISHIFT_IP=`minishift ip` - -$ helm install -n prometheus-dpc --namespace metrics \ - --set rbac.create=true \ - --set openshift=true \ - --set alertmanager.enabled=false \ - --set pushgateway.enabled=false \ - --set server.ingress.hosts[0]=prometheus-dpc.${MINISHIFT_IP}.nip.io \ - charts/prometheus-dpc/ -``` - -**Upgrade** -```console -# Get the MiniShift IP to use in the FQDN of the route -$ export MINISHIFT_IP=`minishift ip` - -$ helm upgrade prometheus-dpc \ - --set rbac.create=true \ - --set openshift=true \ - --set alertmanager.enabled=false \ - --set pushgateway.enabled=false \ - --set server.ingress.hosts[0]=prometheus-dpc.${MINISHIFT_IP}.nip.io \ - charts/prometheus-dpc/ -``` - - -The standard permissions within OpenShift do not allow Prometheus to fully work. As such the following commands must be run. - -```console -# Needed so that the host network, ports and PID are available to the Node Exporter. -$ oc adm policy add-scc-to-user privileged \ - system:serviceaccount:metrics:prometheus-dpc-prometheus-dpc-node-exporter - -# Needed so that the Prometheus server is able to watch v1.Endpoints, v1.Pod, v1.Service and v1.Node resources -$ oc adm policy add-cluster-role-to-user cluster-admin \ - system:serviceaccount:metrics:prometheus-dpc-prometheus-dpc-server - -# Needed so Kube State Metrics can talk to the API server -$ oc adm policy add-cluster-role-to-user cluster-admin \ - system:serviceaccount:metrics:prometheus-dpc-prometheus-dpc-kube-state-metrics -``` - -If your MiniShift IP address was `192.168.64.3` then you would now be able to access Prometheus using the following URL.
    - -[http://prometheus-dpc.192.168.64.3.nip.io](http://prometheus-dpc.192.168.64.3.nip.io) - - - -## Grafana - -There is a [customised](metrics_charts.md#grafana) version of the standard Grafana Helm [Chart](https://github.com/kubernetes/charts/tree/master/stable/grafana) available in the `charts/grafana-dpc/` directory. - -**Notes** - -* If deploying this to a local MiniShift cluster then you can get the IP addess using `minishift ip`. -* This example uses a local MiniShift cluster IP address for the `server.ingress.hosts[0]` value. - - -The standard permissions within OpenShift do not allow Grafana to fully work. As such the following commands must be run. - -```console - -# Needed so that the directories mounted into the container are able to have their -# owner changed. -$ oc adm policy add-scc-to-user anyuid system:serviceaccount:metrics:default - -# Possibly not needed? -$ oc adm policy add-scc-to-user privileged system:serviceaccount:metrics:default -``` - -**Install** -```console -# Get the MiniShift IP to use in the FQDN of the route -$ export MINISHIFT_IP=`minishift ip` - -$ helm install -n grafana-dpc --namespace metrics \ - --set openshift=true \ - --set server.ingress.hosts[0]=grafana-dpc.${MINISHIFT_IP}.nip.io \ - -f charts-values/grafana/values.yaml \ - charts/grafana-dpc/ -``` - -**Upgrade** -```console -# Get the MiniShift IP to use in the FQDN of the route -$ export MINISHIFT_IP=`minishift ip` - -$ helm upgrade grafana-dpc \ - --set openshift=true \ - --set server.ingress.hosts[0]=grafana-dpc.${MINISHIFT_IP}.nip.io \ - -f charts-values/grafana/values.yaml \ - charts/grafana-dpc/ -``` - -if using Oauth then add the additional argumnents to the preceeding commands. - -```console - --set server.setGenericOauth.clientID=XXXXXXXXXXXX \ - --set server.setGenericOauth.clientSecret=YYYYYYYYYYYY \ -``` - -Where `XXXXXXXXXXXX` and `YYYYYYYYYYYY` are the Oauth Client ID and the Oauth Client Secret respectively, i.e. - -```console -$ helm upgrade grafana-dpc \ - --set openshift=true \ - --set server.ingress.hosts[0]=grafana-dpc.${MINISHIFT_IP}.nip.io \ - --set server.setGenericOauth.clientId=bXd7yxVqxsOOSUfGbWv2Gj66YGDD6YSa \ - --set server.setGenericOauth.clientSecret=SnHw1_pA8PBReUPtsPH82H2kFCLebeTUC-CxPyDkD-DuU36wV_gZfxE1jZZsJjk- \ - -f charts-values/grafana/values.yaml \ - charts/grafana-dpc/ -``` - -To get the password for the `admin` user. - -```console -$ oc get secret --namespace metrics grafana-dpc-grafana \ - -o jsonpath="{.data.grafana-admin-password}" | base64 --decode ; echo -``` - -If your MiniShift IP address was `192.168.99.100` then you would now be able to access Prometheus using the following URL.
    - -[http://grafana-dpc.192.168.99.100.nip.io](http://grafana-dpc.192.168.99.100.nip.io) - - -**Notifications** - -The Grafana Helm Chart creates a Slack notification channel as part of the install. However, the webhook URL is a dummy value as the proper value is private. Therefore you must manually add the webhook URL. To do this navigate to the Notification channels screen `-> Alerting -> Notification channels`. Then click `edit` on the `salsa_dpc #bay-build` notification channel. Finally, add the proper URL into the `Url` field and save. - diff --git a/docs/quay.md b/docs/quay.md deleted file mode 100644 index e1b54c1e9..000000000 --- a/docs/quay.md +++ /dev/null @@ -1,73 +0,0 @@ -# Quay - ---- - -This document describes how to setup the [Quay](https://quay.io) Docker Repository to host Bay base images. - ---- - - - - - -## CronJob for nightly builds - - -```code -$ helm install --name quay-build-builder --namespace default \ - --set ROBOT_TOKEN=XXXX \ - --set REPOSITORY=XXXX \ - --set TRIGGER_UUID=XXXX \ - charts/trigger-quay-builds/ --dry-run --debug -``` - - - -# Building quay_build image - -```code -$ docker build -t desdrury/quay_build -f bay/images/Dockerfile.quay_build . - -$ docker push desdrury/quay_build -``` - -**Testing** - -```code -# Using the script directly -$ ROBOT_TOKEN=XXXX \ - REPOSITORY=XXXX \ - TRIGGER_UUID=XXXX \ - scripts/trigger_quay_builds.sh - -# Using Docker -$ docker run --rm \ - --env ROBOT_TOKEN=XXXX \ - --env REPOSITORY=XXXX \ - --env TRIGGER_UUID=XXXX \ - desdrury/quay_build - -# Using OpenShift -# > (to run a Pod) -$ oc run trigger-quay-builds \ - --rm --restart=Never --attach -it \ - --image desdrury/quay_build \ - --image-pull-policy Always \ - --command bash - -# > (To execute within the Pod) -$ ROBOT_TOKEN=XXXX \ - REPOSITORY=XXXX \ - TRIGGER_UUID=XXXX \ - ./trigger_quay_builds.sh -``` - - -## How to get the trigger ID - -```code -## List build triggers for dpc_sdp/builder -$ curl "https://quay.io/api/v1/repository/dpc_sdp/builder/trigger/?repository=dpc_sdp%2Fbuilder" \ - -H 'Authorization: Bearer ' \ - -H 'Content-Type: application/json' -``` \ No newline at end of file diff --git a/docs/tests.md b/docs/tests.md deleted file mode 100644 index ed6874e82..000000000 --- a/docs/tests.md +++ /dev/null @@ -1,69 +0,0 @@ -# Tests - ---- - -This document describes the tests that have been created. - ---- - -## test-host.sh - -This test is designed to check that an infrastructure component, that has been deployed by Helm, is available on both its external facing host name and its internal service name. It will check for a HTTP response code of `200` from both endpoints. - - - -```console -$ scripts/test-host.sh -1. Test that the host of a Helm release is contactable from outside the cluster. -2. Test that a service for a Helm release is contactable within the cluster. - -pre-reqs: - -The Python module 'yq' must be installed. - -usage: - ./test-host.sh -r -h -s -p - -arguments: - -r , --release-name= is the Helm release name to test. - -h , --host-path= is the host path within the Helm release values. - -s , --service-name= is the service name to test. - -p , --service-port= is the service port to test. - -example: - ./test-host.sh -r prometheus-dpc -h ".server.ingress.hosts[0]" -s prometheus-dpc-prometheus-dpc-server -p 80 -``` - -Once the Prometheus server has been deployed, as per [these](metrics_install.md#prometheus) instructions, the following test will validate that it is available. - -```console -$ ./test-host.sh \ - -r prometheus-dpc \ - -h ".server.ingress.hosts[0]" \ - -s prometheus-dpc-prometheus-dpc-server \ - -p 80 - -Found the following host: prometheus-dpc.192.168.99.100.nip.io -Found the following NameSpace: metrics -Host response code: 200 -Service response code: 200 -``` - -Once the Grafana server has been deployed, as per [these](metrics_install.md#grafana) instructions, the following test will validate that it is available. - -```console -$ ./test-host.sh \ - -r grafana-dpc \ - -h ".server.ingress.hosts[0]" \ - -s grafana-dpc-grafana \ - -p 80 - -Found the following host: grafana-dpc.192.168.99.100.nip.io -Found the following NameSpace: metrics -Host response code: 200 -Service response code: 200 -``` - -If the test passes then the result code will be set to `0`. This allows the script to become part of a Pipeline. - -`curl` is used for both tests. For the external host, `curl` is executed on the system where the script is run. Therefore it is important that any proxies are appropriately configured, for example with the `https_proxy` environment variable. For the internal service, `curl` is run on a short-lived `Pod` that is created in the same namespace as the `Service` that it is testing. \ No newline at end of file diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index 283675490..000000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,57 +0,0 @@ -# Troubleshooting - ---- - -This document describes troubleshooting information. - ---- - -## Error from server (Forbidden) - -If you see an error similar to the following. - -```console -Error from server (Forbidden): User "developer" cannot list pods in project "kube-system" -``` - -Ensure that you are logged in as an administrator. On MiniShift do the following. - -```console -$ oc login -u system:admin -``` - - -## Error: could not find tiller - -If you see an error similar to the following. - -```console -Error: could not find tiller -``` - -Create the missing environment variable. - -```console -$ export TILLER_NAMESPACE=tiller -``` - -## ERROR: Python module 'yq' must be installed. -Provide instructions how to debug this error on a Mac. Mac uses the legacy Python v.2.7 which has no module `yq` available. -A possible workaround is to use `pyenv` via `brew install pyenv`. This allows to switch Python version globally or per directory. -https://github.com/pyenv/pyenv - -Steps to install python3 in Mac OS X -```shell -$ brew instal automake -$ brew install libtool -$ brew install pyenv -$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile -$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile -$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n eval "$(pyenv init -)"\nfi' >> ~/.bash_profile -$ exec "$SHELL" -$ pyenv install 3.6.3 -$ pyenv init - -$ pip install jq -$ pip install yq -``` - diff --git a/docs/using_lagoon/backups.md b/docs/using_lagoon/backups.md deleted file mode 100644 index c430814f6..000000000 --- a/docs/using_lagoon/backups.md +++ /dev/null @@ -1,19 +0,0 @@ -# Backups - -Lagoon differentiates between three backup categories: Short-, Mid- and Long-Term Backups. - -## Short-Term Backups - -These Backups are provided by Lagoon itself and are implemented for Databases only. Lagoon will automatically instruct the `mariadb` and `postgres` [services types](./service_types.md) to setup a cron which creates backups once a day (see example [backup script](https://github.com/amazeeio/lagoon/blob/docs/images/mariadb/mysql-backup.sh) for mariadb). These backups are kept for four days and automatically cleaned up after that. - -These Backups are accessible for developers directly with connecting via the [Remote Shell](./remote_shell.md) to the corresponding container (like `mariadb`) and checking the [folder](https://github.com/amazeeio/lagoon/blob/docs/images/mariadb/mysql-backup.sh#L24) where the backups are stored). They can then be downloaded, extracted or in any other way used. - -## Mid-Term Backups - -Mid-Term Backups are not automatically provided by Lagoon and depend heavy on the underlining Infrastructure where Kubernetes and OpenShift are running. Check with your Lagoon Administrator what Backups are created on your infrastructure. - -For amazee.io infrastructure: Every persistent storage and Docker Images are backed up daily for a week, and weekly for a month. If you need such access to such a Backup, check with the Support Team, the will help you. - -## Long-Term Backups - -Long-Term Backups refer to Backups that are kept for multiple months and years. These types of Backups also depend heavy on the underlining Infrastructure. Check with your Lagoon Administrator what Backups are created on your infrastructure. diff --git a/docs/using_lagoon/build_deploy_process.md b/docs/using_lagoon/build_deploy_process.md deleted file mode 100644 index 9403786c7..000000000 --- a/docs/using_lagoon/build_deploy_process.md +++ /dev/null @@ -1,100 +0,0 @@ -# The Lagoon Build and Deploy Process - -This document describes what actually happens during a Build and Deployment, it is heavy simplified from what actually happens, but it will help you to understand what is happening under the hood every time that Lagoon deploys new code for you. - -## 1. Setup OpenShift Project / Kubernetes Namespace for Environment - -As first Lagoon checks if the OpenShift Project / Kubernetes Namespace for the given Environment is existing and correctly setup. It will make sure that we have the needed service accounts, create secrets and will configure environment variables into a ConfigMap `lagoon-env` which is filled with information like the environment type and name, the Lagoon project name, and so on. - -## 2. Git Checkout & Merge - -As next, Lagoon will checkout your code from Git. It needs that to have access to read the `.lagoon.yml` and `docker-compose.yml` but also to build the Docker Images. - -Based on how the deployment has been triggered different things will happen: - -#### Branch Webhook Push - -If the deployment is triggered via a Webhook and is for a single Branch, Lagoon will checkout the Git SHA which is included in the Webhook. This means even if you push code to the Git Branch twice, there will be two deployments with exactly the code that was pushed, not just the newest code in the git branch. - -#### Branch REST trigger - -If you trigger a deployment via the REST API and do NOT define a `sha` in the POST payload, Lagoon will just checkout the branch with the newest code without a specific given Git Sha. - -#### Pull Requests - -If the deployment is a pull request deployment, Lagoon will load the Base and the Head Branch and SHAs for the Pull Request and will: - -- checkout the base branch (the branch the Pull Request points too) -- merge the head branch (the branch that the Pull Request originates from) on top of the base branch - -If the merge fails, Lagoon will also stop and inform you about this. - -## 3. Build Image - -For each Service defined in the `docker-compose.yml` Lagoon will check if Images need to be built or not. If they need to be built, this will happen now. The order of building is based on the order they are configured in `docker-compose.yml` and some build arguments are injected: - -- `LAGOON_GIT_SHA` -- `LAGOON_GIT_BRANCH` -- `LAGOON_PROJECT` -- `LAGOON_BUILD_TYPE` (either `pullrequest`, `branch` or `promote`) -- `LAGOON_SSH_PRIVATE_KEY` the SSH private key that is used to clone the source repository, use `RUN /lagoon/entrypoints/05-ssh-key.sh` to convert the build argument into an actual key at `/home/.ssh/key` which will be used by ssh and git automatically. For safety, remove the key again via `RUN rm /home/.ssh/key` -- `LAGOON_GIT_SOURCE_REPOSITORY` the full Git URL of the Source Repository - -Plus if this is a Pull Request build: - -- `LAGOON_PR_HEAD_BRANCH` -- `LAGOON_PR_HEAD_SHA` -- `LAGOON_PR_BASE_BRANCH` -- `LAGOON_PR_BASE_SHA` -- `LAGOON_PR_TITLE` - -Additionally for each already built image, it's name is also injected. If your docker-compose.yml defines to first build the `cli` image and then the `nginx` image, the name of the nginx image is injected as `NGINX_IMAGE`. - -## 4. Configure OpenShift/Kubernetes Services and Routes - -As next Lagoon will configure OpenShift/Kubernetes with all Services and Routes that are defined from the service types, plus possible additional custom routes that you have defined in `.lagoon.yml`. - -In this step it will expose all defined routes in the `LAGOON_ROUTES` as comma separated URLs. It will also define one Route as the "main" route, in this order: - -1. If custom routes defined: the first defined custom route in `.lagoon.yml` -2. The first auto generated one from a service defined in `docker-compose.yml` -3. None - -The "main" route is injected via the `LAGOON_ROUTE` environment variable. - -## 5. Push and Tag Images - -Now it is time to push the previous built Docker Images into the internal Docker Image Registry. - -For services that didn't define a Dockerfile to be built in `docker-compose.yml` and just gave a Image, they are tagged via `oc tag` in the OpenShift project, which will cause the internal Docker Image Registry to know about the images, so that hey can be used in containers. - -## 6. Persistent Storage - -Lagoon will now create persistent storage (PVC) for each service that needs and requested a persistent storage. - -## 7. Cronjobs - -For each service that requests a Cronjob (like the mariadb), plus for each custom cronjob defined in `.lagoon.yml` Lagoon will now generate the cronjob environment variables which are later injected into the DeploymentConfigs. - -## 8. DeploymentConfigs, Statefulsets, Deamonsets - -This is probably the most important step. Based on the defined service type, Lagoon will create the DeploymentConfigs, Statefulset or Daemonsets for the service. -It will include all previously gathered information like the Cronjobs, the location of persistent storage, the pushed images and so on. - -Creation of these Objects will also automatically cause OpenShift/Kubernetes to trigger new deployments of the Pods if necessary, like when a environment variable has changed or an Image has changed. But if there is no change, there will be no deployment! This means if you just update the PHP code in your application, the Varnish, Solr, MariaDB, Redis and any other service that is defined but does not include your code will not be deployed. This makes everything much much faster. - -## 9. Wait for all rollouts to be done - -Now Lagoon waits, it waits for all just triggered deployments of the new pods to be finished, plus their healthchecks to be successful. - -If any of the deployments or healtchecks fails, the deployment will be stopped here and you will be informed via the defined Notification systems (like Slack) that the deployment has failed. - -## 10. Run defined post-rollout tasks - -Now Lagoon will check the `.lagoon.yml` file for defined tasks in `post-rollout` and will run them one by one in the defined services. - -If any of them fails, Lagoon will immediately stop and notify you. - -## 11. Success - -If all went correct and nothing threw any error, Lagoon will mark this build as successful and inform you via defined notifications. \ No newline at end of file diff --git a/docs/using_lagoon/configure_webhooks.md b/docs/using_lagoon/configure_webhooks.md deleted file mode 100644 index 867333efc..000000000 --- a/docs/using_lagoon/configure_webhooks.md +++ /dev/null @@ -1,44 +0,0 @@ -# Configure Webhooks -From your Lagoon administrator, you will also need the route to the -webhook-handler. You will add this to your repository as an outgoing webhook, -and choose which events to send to Lagoon. Typically you will send all Push and -Pull Request \ Merge Request events. In Lagoon it is possible to add a -regular expression to determine which branches and pull requests actually result in a deploy. - -If you are an amazee.io customer, the webhook url is: -`https://hooks.lagoon.amazeeio.cloud`. - -## Github - -1. Proceed to Settings -> Webhooks -> `Add webhook` in your repository -2. The `Payload URL` is the route to the webhook-handler of your Lagoon instance -3. Set `Content type` to `application\json` -![Github Webhook Configuration 1](/images/gh_webhook_1.png) -4. Choose which events will trigger your webhook. It is our suggestion that you send `push` and `Pull request` events, and then filter further in the Lagoon configuration of your project. -![Github Webhook Configuration 2](/images/gh_webhook_2.png) -5. `Add webhook` - -## GitLab - -1. Navigate to Settings -> Integrations for your repository -2. The `URL` is the route to the webhook-handler of your Lagoon instance -3. Set the `Trigger` for which events will send a notification to Lagoon. It is our suggestion that you send `Push events` and `Merge request events` events, and then filter further in the Lagoon configuration of your project. -![Gitlab Webhook Setup](/images/gl_webhook_1.png) -4. `Add webhook` - -## BitBucket - -1. Navigate to Settings -> Webhooks -> Add new webhook in your repository -2. `Title` is for your reference, `URL` is the route to the webhook-handler of your Lagoon instance -3. `Choose from a full list of triggers` and select - * Repository - * push - * Pull Request - * Created - * Updated - * Approved - * Approval Removed - * Merged - * Declined -![Bitbucket Webhook Setup](/images/bb_webhook_1.png) -4. `Save` diff --git a/docs/using_lagoon/docker-compose_yml.md b/docs/using_lagoon/docker-compose_yml.md deleted file mode 100644 index 44adc9cda..000000000 --- a/docs/using_lagoon/docker-compose_yml.md +++ /dev/null @@ -1,152 +0,0 @@ -# docker-compose.yml file -The `docker-compose.yml` (or also `docker-compose.yaml`) is used by Lagoon to: - -* learn which services/containers should be deployed -* how the images for the containers are built -* additional configurations like persistent volumes - -Docker-compose (the tool) is very strict in validating the content of the yaml file, so we can only do any configurations within `labels` of a service definition. - -**Important**: Lagoon only reads the labels, service names, image names and build definitions from a docker-compose.yml file. Definitions like: Ports, Environment Variables, Volumes, Networks, Links, Users, etc. are IGNORED. This is intentional as the docker-compose file is there to define your local environment configuration. Lagoon learns from the `lagoon.type` the type of service you are deploying and from that knows about ports, networks and any additional configuration that this service might need. - -Here an easy example of a docker-compose.yml file for Drupal: - -``` -services: - - nginx: - build: - context: . - dockerfile: Dockerfile.nginx - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/web/sites/default/files/ - - php: - build: - context: . - dockerfile: Dockerfile.php - labels: - lagoon.type: nginx-php-persistent - lagoon.name: nginx - lagoon.persistent: /app/web/sites/default/files/ - - mariadb: - image: amazeeio/mariadb-drupal - labels: - lagoon.type: mariadb -``` - -#### `services` - -This defines all your "services" you like to deploy. 'Unfortunately' docker-compose calls them services, even though they are actually containers. - -The name of the service (`nginx`, `php`, `mariadb` in the example above) is used by Lagoon as the name of the Pod that is generated, plus also any additional Kubernetes Objects that are created based on the defines `lagoon.type`, which could be things like Services, Routes, PVCs, etc. - -### Docker Images - -#### `build` - -If you would like Lagoon to build a Dockerfile for your service during every deployment, you can define it here: - -`build` - -* `context` - * The build context path that should be passed on into the `docker build` command -* `dockerfile:` - * Location and name of the Dockerfile that should be build - -Important: Lagoon does NOT support the short version of `build: ` and will fail if it finds such a definition. - -#### `image` - -If you don't need to build a Dockerfile and just want to use an existing Dockerfile, define it via `image`. - -### Types - -Lagoon needs to know what type of service you are deploying in order to configure the correct Kubernetes and OpenShift Objects. - -This is done via the `lagoon.type` label. There are many different types to choose from, check [Service Types](./service_types.md) to see all of them and their additional configuration possibilities. - -#### Skip/Ignore containers - -If you like Lagoon to ignore a service completely, like for the case that you need a container only during local development, just give it the type `none`. - -### Persistent Storage - -Some containers need persistent storage. While Lagoon knows for many service types where that persistent storage needs to go. For example for a mariadb container it knows that the persistent storage should be put into `/var/lib/mysql` and puts it there automatically with the need to define that. -For some situations though Lagoon needs your help to know where to put the persistent storage: - -* `lagoon.persistent` - the **absolute** path where the persistent storage should be mounted (the above example uses `/app/web/sites/default/files/` which is where Drupal expects it's persistent storage) -* `lagoon.persistent.name` - tells Lagoon to not create a new persistent storage for that service, but instead mounts the persistent storage of another defined service into this service -* `lagoon.persistent.size` - the size of persistent storage you require (Lagoon usually gives you minimum `5G` of persistent storage, if you need more define it here) -* `lagoon.persistent.class` - by default Lagoon automatically assigns the right Storage Class for your service (like SSDs for mysql, Bulk Storage for Nginx, etc.). If you need to overwrite this, you can do so here. - This is highly depending on the underlining Kubernetes/OpenShift that Lagoon runs on. Ask your Lagoon Administrator about this. - -### Multi Container Pods - -Kubernetes and OpenShift don't deploy plain Containers, instead they deploy Pods, which each include a single or multiple containers. Usually Lagoon creates for each defined docker-compose service a single Pod with a Container inside. For some cases though, we need to put two containers inside a single pod, as these containers are so depending on each other, that they should always stay together. An example for such a situation is the PHP and Nginx container that both contain PHP code of a webapplication like Drupal. - -For these cases it is possible to tell Lagoon which services should stay together, this is done the following way: - -1. Define both services with a `lagoon.type` that expects two containers (in the example this is `nginx-php-persistent` defined on the `nginx` and `php` services) -2. Link the second service/container with the first one, with defining the label `lagoon.name` of the second one with the first one. (in the example this is done with defining `lagoon.name: nginx`). - -This will cause Lagoon to realise that the `nginx` and `php` containers are combined in a Pod that will be called `nginx`. - -Lagoon still needs to understand which of the two services are the actual individual service type (`nginx` and `php` in this case). It does this with searching for service names with the same name that are given by the type, so `nginx-php-persistent` expects a service with the name `nginx` and one with `php` in the docker-compose.yml. If for any reason you want to use different names for the services or you maybe need two pods with the type `nginx-php-persistent` there is an additional label `lagoon.deployment.servicetype` which can be used to define the actual service type. - -An example: - -``` - web: - build: - context: . - dockerfile: Dockerfile.nginx - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/web/sites/default/files/ - lagoon.name: nginx - lagoon.deployment.servicetype: nginx - phehaphe: - build: - context: . - dockerfile: Dockerfile.php - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/web/sites/default/files/ - lagoon.name: nginx - lagoon.deployment.servicetype: php -``` - -As you can see the services are called `web` (which is the nginx container) and `phehaph` (which is Swiss-German for `php`). In order for Lagoon to realize which one is the `nginx` and which one is the `php` container, it is defined via `lagoon.deployment.servicetype: nginx` and `lagoon.deployment.servicetype: php`. - -Additionally twice the `lagoon.name: nginx` is defined, which will cause Lagoon to give the Pod the name `nginx` and not `web` (Tip: Do not do this, it's way too confusing, name the things the same). - - -### Advanced Usage - -#### Custom Templates - -If you need some changes on the OpenShift Templates, you can define your own template via `lagoon.template`. Check out the shipped Templates from the [templates folder of `oc-build-deploy-dind`](https://github.com/amazeeio/lagoon/tree/master/images/oc-build-deploy-dind/openshift-templates). Important: The template is called with `oc process`, so you should define the same parameters like in the default templates. - -You can also overwrite the templates only for a specific environment, this is done in the [`.lagoon.yml`](/using_lagoon/lagoon_yml.md/#environmentsnametypes) - -#### Custom Rollout Monitor Types - -By default Lagoon expects that the way services from custom templates are rolled out is done via a `DeploymentConfig` object within Openshift/Kubernetes and monitors the rollout based on such object. In some cases the services that are defined via custom deployment need a different way of monitoring, this can be defined via `lagoon.rollout`: - -- `deploymentconfig` (this is the default) - expects a `DeplomentConfig` object in the template for the service -- `statefulset` - expects a `Statefulset` object in the template for the service -- `daemonset` - expects a `Daemonset` object in the template for the service -- `false` - will not monitor any rollouts and just be happy of the template applies and does not throw any errors - -You can also overwrite the rollout only for a specific environment, this is done in the [`.lagoon.yml`](/using_lagoon/lagoon_yml.md/#environmentsnamerollouts) - -#### Custom Type - -Feeling adventurous and would like to do something completely customized? Welcome to the Danger-Zone! - -With defining a service as `lagoon.type: custom`, you can tell Lagoon to not use any predefined service type templates and pass your full own custom yaml file. - -This also expects the label `lagoon.template` to be defined with the path to the yaml file where you define all the needed Kubernetes Objects to be executed. In here you can define your own OpenShift Templates like they ones in the [templates folder of `oc-build-deploy-dind`](https://github.com/amazeeio/lagoon/tree/master/images/oc-build-deploy-dind/openshift-templates). Important: The template is called with `oc process`, so you should define the same parameters like in the default templates. - diff --git a/docs/using_lagoon/docker_images/nginx.md b/docs/using_lagoon/docker_images/nginx.md deleted file mode 100644 index 54b43eac6..000000000 --- a/docs/using_lagoon/docker_images/nginx.md +++ /dev/null @@ -1,48 +0,0 @@ -# nginx Image -amazee.io Alpine 7 Dockerfile with nginx installed, based on the official openresty Alpine images at (https://hub.docker.com/r/openresty/openresty/). - -This Dockerfile is intended to be used as base for any webservers within amazee.io. By default the nginx only serves static files. If you need php have a look at the php-fpm image and use nginx and php-fpm in tandem. - -## amazee.io & OpenShift adaptions -This image is prepared to be used on amazee.io which leverages OpenShift. There are therefore some things already done: - -- Folder permissions are automatically adapted with [`fix-permissions`](https://github.com/sclorg/s2i-base-container/blob/master/core/root/usr/bin/fix-permissions) so this image will work with a random user and therefore also on OpenShift. -- The files within `/etc/nginx/*` are parsed through [envplate](https://github.com/kreuzwerker/envplate) with an container-entrypoint. - -## Included Nginx configuration (static-files.conf) -By default nginx only serves static files - this can be used for static sites that don't require a database or php components e.g. Static site generators like Hugo, Jekyll or Gatsby. Simply build the content during the build process and inject it into the nginx container. - -## Helpers -### redirects-map.conf -In order to create redirects we have the redirects-map.conf in place. This helps you to redirect marketing domains to subsites or do non-www to www redirects. -If you have a lot of redirects we suggest to have the `redirects-map.conf` stored next to your code for easier maintainability. -If you just have a few redirects there's a handy trick to create the redirects with a `RUN` command in your Dockerfile.nginx. - - -Example for redirecting `www.example.com` to `example.com` and preserving the request. - -``` -RUN echo "~^www.example.com http://example.com\$request_uri;" >> /etc/nginx/redirects-map.conf - -``` - -To get more details about the various types of redirects that can be achieved see the documentation within the [redirects-map.conf](https://github.com/amazeeio/lagoon/blob/master/images/nginx/redirects-map.conf) directly. - -After you put the `redirects-map.conf` in place you also need to include it in your `Dockerfile.nginx` in order to get -the configuration file into your build. - -``` -COPY redirects-map.conf /etc/nginx/redirects-map.conf -``` - -### Basic Authentication -If you want to protect your site via Basic Authentication you can do this by defining the environment variables `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` within your .lagoon.env.environment files. - - -## Environment Variables -Environment variables are meant to do common behavior changes of php. - -| Environment Variable | Default | Description | -| --------------------------------- | --------- | ---------------------------------------------- | -| `BASIC_AUTH_USERNAME` | (not set) | Username for basic Authentication | -| `BASIC_AUTH_PASSWORD` | (not set) | Password for basic authentication (unencrypted)| diff --git a/docs/using_lagoon/docker_images/php-fpm.md b/docs/using_lagoon/docker_images/php-fpm.md deleted file mode 100644 index 39f4a3dcc..000000000 --- a/docs/using_lagoon/docker_images/php-fpm.md +++ /dev/null @@ -1,70 +0,0 @@ -# php-fpm Image - -amazee.io Alpine 7 Dockerfile with php-fpm installed, based on the official PHP Alpine images at (https://hub.docker.com/_/php/) - -This Dockerfile is intended to be used as an base for any php needs within amazee.io. This image itself does not create a webserver, rather just an php-fpm fastcgi listener. You maybe need to adapt the php-fpm pool config. - -## amazee.io & OpenShift adaptions - -This image is prepared to be used on amazee.io which leverages OpenShift. There are therefore some things already done: - -- Folder permissions are automatically adapted with [`fix-permissions`](https://github.com/sclorg/s2i-base-container/blob/master/core/root/usr/bin/fix-permissions) so this image will work with a random user and therefore also on OpenShift. -- The `/usr/local/etc/php/php.ini` and `/usr/local/etc/php-fpm.conf` plus all files within `/usr/local/etc/php-fpm.d/` are parsed through [envplate](https://github.com/kreuzwerker/envplate) with an container-entrypoint. -- See the [Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/php/fpm/Dockerfile) for installed php extensions -- To install further extensions, extend your Dockerfile from this image, and install extensions according to the docs, under the heading ["How to install more PHP extensions"](https://github.com/docker-library/docs/blob/master/php/README.md#how-to-install-more-php-extensions) - -## Included php config - -The included php config contains sane values that will make the creation of php pools configs easier. Here a list these, check `/usr/local/etc/php.ini`, `/usr/local/etc/php-fpm.conf` for all of it: - -- `max_execution_time = 900` (changeable via `PHP_MAX_EXECUTION_TIME`) -- `realpath_cache_size = 256k` for handling big php projects -- `memory_limit = 400M` for big php projects (changeable via `PHP_MEMORY_LIMIT`) -- `opcache.memory_consumption = 265` for big php projects -- `opcache.enable_file_override = 1` and `opcache.huge_code_pages = 1` for faster php -- `display_errors = Off` and `display_startup_errors = Off` for sane production values (changeable via `PHP_DISPLAY_ERRORS` and `PHP_DISPLAY_STARTUP_ERRORS`) -- `upload_max_filesize = 2048M` for big file uploads -- `apc.shm_size = 32m` and `apc.enabled = 1` (changeable via `PHP_APC_SHM_SIZE` and `PHP_APC_ENABLED`) -- php-fpm error logging happens in stderr - -Hint: If you don't like any of these configs, you have three possibilities: -1. If they are changeable via environment variables, use them (preferred version, see list of environment variables below) -2. Create your own fpm-pool config and set configs them via `php_admin_value` and `php_admin_flag` in there (learn more about them [here](http://php.net/manual/en/configuration.changes.php) - yes this refers to Apache, but it is also the case for php-fpm). _Important:_ - 1. If you like to provide your own php-fpm pool, overwrite the file `/usr/local/etc/php-fpm.d/www.conf` with your own config or remove this file if you like another name. If you don't do that the provided pool will be started! - 2. PHP Values with the [`PHP_INI_SYSTEM` changeable mode](http://php.net/manual/en/configuration.changes.modes.php) cannot be changed via an fpm-pool config. They need to changed either via already provided Environment variables or: -3. Provide your own `php.ini` or `php-fpm.conf` file (least preferred version) - -## default fpm-pool - -This image is shipped with an fpm-pool config ([`php-fpm.d/www.conf`](https://github.com/amazeeio/lagoon/blob/master/images/php/fpm/php-fpm.d/www.conf)) that creates a fpm-pool and listens on port 9000. This is because we try to provide an image which covers already most needs for PHP and so you don't need to create your own. You are happy to do so if you like though :) Here a short description of what this file does: - -- listens on port 9000 via ipv4 and ipv6 -- uses the pm `dynamic` and creates between 2-50 children -- respawns fpm pool children after 500 requests to prevent memory leaks -- replies with `pong` when making an fastcgi request to `/ping` (good for automated testing if the pool started) -- `catch_workers_output = yes` to see php errors -- `clear_env = no` to be able to inject PHP environment variables via regular Docker environment variables - -## Environment Variables - -Environment variables are meant to do common behavior changes of php. - -| Environment Variable | Default | Description | -| --------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `PHP_MAX_EXECUTION_TIME` | `900` | Maximum execution time of each script, in seconds, [see php.net](http://php.net/max-execution-time) | -| `PHP_MAX_INPUT_VARS` | `2000` | How many input variables will be accepted, [see php.net](http://php.net/manual/en/info.configuration.php#ini.max-input-vars) -| `PHP_MAX_FILE_UPLOADS` | `20` | The maximum number of files allowed to be uploaded simultaneously, [see php.net](http://php.net/manual/en/ini.core.php#ini.max-file-uploads)| -| `PHP_MEMORY_LIMIT` | `400M` | Maximum amount of memory a script may consume, [see php.net](http://php.net/memory-limit) | -| `PHP_DISPLAY_ERRORS` | `Off` | This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user, [see php.net](http://php.net/display-errors) | -| `PHP_DISPLAY_STARTUP_ERRORS` | `Off` | Even when display_errors is on, errors that occur during PHP's startup sequence are not displayed. It's strongly recommended to keep it off, except for debugging., [see php.net](http://php.net/display-startup-errors) | -| `PHP_APC_SHM_SIZE` | `32m` | The size of each shared memory segment given, [see php.net](http://php.net/manual/en/apc.configuration.php#ini.apc.shm-size) | -| `PHP_APC_ENABLED` | `1` | Can be set to 0 to disable APC, [see php.net](http://php.net/manual/en/apc.configuration.php#ini.apc.enabled) | -| `XDEBUG_ENABLED` | (not set) | Used to enable xdebug extension, [see php.net](http://php.net/manual/en/apc.configuration.php#ini.apc.enabled) | -| `PHP_FPM_PM_MAX_CHILDREN` | `50` | The the maximum number of child processes [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `PHP_FPM_PM_START_SERVERS` | `2` | The number of child processes created on startup. [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `2` | The desired minimum number of idle server processes. [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `2` | The desired maximum number of idle server processes. [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `PHP_FPM_PM_PROCESS_IDLE_TIMEOUT` | `60s` | The number of seconds after which an idle process will be killed. [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `PHP_FPM_PM_MAX_REQUESTS` | `500` | The number of requests each child process should execute before respawning. [see php.net](http://php.net/manual/en/install.fpm.configuration.php) | -| `NEWRELIC_ENABLED` | `false` | Enable NewRelic performance monitoring, needs`NEWRELIC_LICENSE` be configured | -| `NEWRELIC_LICENSE` | (not set) | NewRelic License to be used, Important: `NEWRELIC_ENABLED` needs to be set to `true` in order for NewRelic to be enabled | diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/.dockerignore b/docs/using_lagoon/drupal/drupal7-mariadb/.dockerignore deleted file mode 100644 index 191381ee7..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -.git \ No newline at end of file diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/.lagoon.yml b/docs/using_lagoon/drupal/drupal7-mariadb/.lagoon.yml deleted file mode 100644 index 2c419e60e..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/.lagoon.yml +++ /dev/null @@ -1,24 +0,0 @@ -docker-compose-yaml: docker-compose.yml - -tasks: - post-rollout: - - run: - name: env variables - command: env - service: cli - - run: - name: drush updb - command: drush updb --cache-clear=0 - service: cli - - run: - name: drush cc all - command: drush cc all - service: cli - -environments: - master: - cronjobs: - - name: drush cron - schedule: "H * * * *" # this will run the cron once per Hour - command: drush cron - service: cli diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.cli b/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.cli deleted file mode 100644 index 47081bc6f..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.cli +++ /dev/null @@ -1,3 +0,0 @@ -FROM amazeeio/php:7.1-cli-drupal - -COPY . /app diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.nginx b/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.nginx deleted file mode 100644 index df2ff34df..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.nginx +++ /dev/null @@ -1,7 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as cli - -FROM amazeeio/nginx-drupal - -COPY --from=cli /app /app - diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.php b/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.php deleted file mode 100644 index 8b59f9a13..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/Dockerfile.php +++ /dev/null @@ -1,6 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as cli - -FROM amazeeio/php:7.1-fpm - -COPY --from=cli /app /app diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/docker-compose.yml b/docs/using_lagoon/drupal/drupal7-mariadb/docker-compose.yml deleted file mode 100644 index bb4388754..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/docker-compose.yml +++ /dev/null @@ -1,120 +0,0 @@ -version: '2.3' - -x-lagoon-project: - # Lagoon project name (leave `&lagoon-project` when you edit this) - &lagoon-project drupal7-example - -x-volumes: - &default-volumes - # Define all volumes you would like to have real-time mounted into the docker containers - volumes: - - .:/app:delegated - -x-environment: - &default-environment - LAGOON_PROJECT: *lagoon-project - # Route that should be used locally - LAGOON_ROUTE: http://drupal7.docker.amazee.io - # Uncomment if you like to have the system behave like in production - #LAGOON_ENVIRONMENT_TYPE: production - # Uncomment to enable xdebug and then restart via `docker-compose up -d` - #XDEBUG_ENABLE: "true" - - -services: - - cli: # cli container, will be used for executing composer and any local commands (drush, drupal, etc.) - build: - context: . - dockerfile: Dockerfile.cli - image: *lagoon-project # this image will be reused as `CLI_IMAGE` in subsequent Docker builds - labels: - # Lagoon Labels - lagoon.type: cli-persistent - lagoon.persistent.name: nginx # mount the persistent storage of nginx into this container - lagoon.persistent: /app/sites/default/files/ # location where the persistent storage should be mounted - << : *default-volumes # loads the defined volumes from the top - volumes_from: # mount the ssh-agent from the pygmy or cachalot ssh-agent - - container:amazeeio-ssh-agent - environment: - << : *default-environment # loads the defined environment variables from the top - - nginx: - build: - context: . - dockerfile: Dockerfile.nginx - args: - CLI_IMAGE: *lagoon-project # Inject the name of the cli image - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - LAGOON_LOCALDEV_URL: nginx-drupal7.docker.amazee.io # generate another route for nginx, by default we go to varnish - networks: - - amazeeio-network - - default - - php: - build: - context: . - dockerfile: Dockerfile.php - args: - CLI_IMAGE: *lagoon-project - labels: - lagoon.type: nginx-php-persistent - lagoon.name: nginx # we want this service be part of the nginx pod in Lagoon - lagoon.persistent: /app/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - - - mariadb: - image: amazeeio/mariadb-drupal - labels: - lagoon.type: mariadb - ports: - - "3306" # exposes the port 3306 with a random local port, find it with `docker-compose port mariadb 3306` - environment: - << : *default-environment - - ## Uncomment for Redis - # redis: - # image: amazeeio/redis - # labels: - # lagoon.type: redis - # environment: - # << : *default-environment - - ## Uncomment for Solr - # solr: - # image: amazeeio/solr:6.6-drupal - # labels: - # lagoon.type: solr - # ports: - # - "8983" # exposes the port 8983 with a random local port, find it with `docker-compose port solr 8983` - # environment: - # << : *default-environment - - varnish: - image: amazeeio/varnish-drupal - labels: - lagoon.type: varnish - links: - - nginx # links varnish to the nginx in this docker-compose project, or it would try to connect to any nginx running in docker - environment: - << : *default-environment - VARNISH_BYPASS: "true" # by default we bypass varnish, change to 'false' or remove in order to tell varnish to cache if possible - networks: - - amazeeio-network - - default - -networks: - amazeeio-network: - external: true diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/drush/aliases.drushrc.php b/docs/using_lagoon/drupal/drupal7-mariadb/drush/aliases.drushrc.php deleted file mode 100644 index 9c1679ab7..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/drush/aliases.drushrc.php +++ /dev/null @@ -1,19 +0,0 @@ - 'cache,cache_*,history,sessions,watchdog,feeds_log'); -$command_specific['sql-dump'] = array('structure-tables-list' => 'cache,cache_*,history,sessions,watchdog,feeds_log'); diff --git a/docs/using_lagoon/drupal/drupal7-mariadb/sites/default/all.settings.php b/docs/using_lagoon/drupal/drupal7-mariadb/sites/default/all.settings.php deleted file mode 100755 index 5cecb9a3a..000000000 --- a/docs/using_lagoon/drupal/drupal7-mariadb/sites/default/all.settings.php +++ /dev/null @@ -1,15 +0,0 @@ - 'mysql', - 'database' => getenv('MARIADB_DATABASE') ?: 'drupal', - 'username' => getenv('MARIADB_USERNAME') ?: 'drupal', - 'password' => getenv('MARIADB_PASSWORD') ?: 'drupal', - 'host' => getenv('MARIADB_HOST') ?: 'mariadb', - 'port' => 3306, - 'prefix' => '', - ); -} - - // Lagoon Solr connection - // WARNING: you have to create a search_api server having "solr" machine name at - // /admin/config/search/search-api/add-server to make this work. - // Also you need to have the search_api_override module installed and enabled - https://www.drupal.org/project/search_api_override - if (getenv('LAGOON')) { - // Override search API server settings fetched from default configuration. - $conf['search_api_override_mode'] = 'load'; - $conf['search_api_override_servers']['solr']['name'] = 'Lagoon Solr - Environment:' . getenv('LAGOON_PROJECT'); - $conf['search_api_override_servers']['solr']['options']['host'] = (getenv('SOLR_HOST') ?: 'solr'); - $conf['search_api_override_servers']['solr']['options']['port'] = 8983; - $conf['search_api_override_servers']['solr']['options']['path'] = '/solr/' . (getenv('SOLR_CORE') ?: 'drupal'); - $conf['search_api_override_servers']['solr']['options']['http_user'] = (getenv('SOLR_USER') ?: ''); - $conf['search_api_override_servers']['solr']['options']['http_pass'] = (getenv('SOLR_PASSWORD') ?: ''); - $conf['search_api_override_servers']['solr']['options']['excerpt'] = 0; - $conf['search_api_override_servers']['solr']['options']['retrieve_data'] = 0; - $conf['search_api_override_servers']['solr']['options']['highlight_data'] = 0; - $conf['search_api_override_servers']['solr']['options']['http_method'] = 'POST'; - } - - // Lagoon Varnish & reverse proxy settings. - if (getenv('LAGOON')) { - $varnish_control_port = getenv('VARNISH_CONTROL_PORT') ?: '6082'; - $varnish_hosts = explode(',', getenv('VARNISH_HOSTS') ?: 'varnish'); - array_walk($varnish_hosts, function (&$value, $key) use ($varnish_control_port) { - $value .= ":$varnish_control_port"; - }); - - $conf['reverse_proxy'] = TRUE; - $conf['reverse_proxy_addresses'] = array_merge(explode(',', getenv('VARNISH_HOSTS')), array('varnish')); - $conf['varnish_control_terminal'] = implode($varnish_hosts, " "); - $conf['varnish_control_key'] = getenv('VARNISH_SECRET') ?: 'lagoon_default_secret'; - $conf['varnish_version'] = 4; - } - - // Base URL. - if (getenv('LAGOON_ROUTE')) { - $proto = isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) ? $_SERVER["HTTP_X_FORWARDED_PROTO"] : 'http'; - $base_url = $proto . "://" . $_SERVER["HTTP_HOST"]; - } - - // Temp directory. - if (getenv('TMP')) { - $conf['file_temporary_path'] = getenv('TMP'); - } - - // Hash Salt. - if (getenv('LAGOON')) { - $drupal_hash_salt = hash('sha256', getenv('LAGOON_PROJECT')); - } - - // Loading settings for all environment types. - if (file_exists(__DIR__ . '/all.settings.php')) { - include __DIR__ . '/all.settings.php'; - } - - // Environment specific settings files. - if (getenv('LAGOON_ENVIRONMENT_TYPE')) { - if (file_exists(__DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php')) { - include __DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php'; - } - } - - // Last: this servers specific settings files. - if (file_exists(__DIR__ . '/settings.local.php')) { - include __DIR__ . '/settings.local.php'; - } diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.dockerignore b/docs/using_lagoon/drupal/drupal8-composer-mariadb/.dockerignore deleted file mode 100644 index 1972606e6..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.git -vendor -web/sites/default/files diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.gitignore b/docs/using_lagoon/drupal/drupal8-composer-mariadb/.gitignore deleted file mode 100644 index 1ff7d25cb..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# Ignore directories generated by Composer -/drush/contrib/ -/vendor/ -/web/core/ -/web/modules/contrib/ -/web/themes/contrib/ -/web/profiles/contrib/ -/web/libraries/ - -# Ingore files that are only for the current local environment -web/sites/*/settings.local.php -web/sites/*/services.local.yml - -# Ignore Drupal's file directory -/web/sites/*/files/ - -# Ignore SimpleTest multi-site environment. -/web/sites/simpletest - -# Ignore files generated by PhpStorm -/.idea/ \ No newline at end of file diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.lagoon.yml b/docs/using_lagoon/drupal/drupal8-composer-mariadb/.lagoon.yml deleted file mode 100644 index 77ea40862..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/.lagoon.yml +++ /dev/null @@ -1,29 +0,0 @@ -docker-compose-yaml: docker-compose.yml - -tasks: - post-rollout: - - run: - name: env variables - command: env - service: cli - - run: - name: drush cim - command: drush -y cim - service: cli - - run: - name: drush cr - command: drush -y cr - service: cli - - - -environments: - master: - cronjobs: - - name: drush cron - schedule: "H * * * *" # this will run the cron once per hour - command: drush cron - service: cli - # routes: - # - varnish: - # - "domain.com" diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.cli b/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.cli deleted file mode 100644 index 873056626..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.cli +++ /dev/null @@ -1,11 +0,0 @@ -FROM amazeeio/php:7.2-cli-drupal - -COPY composer.json composer.lock /app/ -COPY scripts /app/scripts -# Uncomment if you have a patches directory in your Drupal Installation -# COPY patches /app/patches -RUN composer install --prefer-dist --no-dev --no-suggest --optimize-autoloader --apcu-autoloader -COPY . /app - -# Define where the Drupal Root is located -ENV WEBROOT=web \ No newline at end of file diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.nginx b/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.nginx deleted file mode 100644 index 237595a9e..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.nginx +++ /dev/null @@ -1,9 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as cli - -FROM amazeeio/nginx-drupal - -COPY --from=cli /app /app - -# Define where the Drupal Root is located -ENV WEBROOT=web diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.php b/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.php deleted file mode 100644 index 0c91f03db..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/Dockerfile.php +++ /dev/null @@ -1,6 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as cli - -FROM amazeeio/php:7.2-fpm - -COPY --from=cli /app /app diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/docker-compose.yml b/docs/using_lagoon/drupal/drupal8-composer-mariadb/docker-compose.yml deleted file mode 100644 index 82deecabc..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/docker-compose.yml +++ /dev/null @@ -1,120 +0,0 @@ -version: '2.3' - -x-lagoon-project: - # Lagoon project name (leave `&lagoon-project` when you edit this) - &lagoon-project drupal-example - -x-volumes: - &default-volumes - # Define all volumes you would like to have real-time mounted into the docker containers - volumes: - - .:/app:delegated - -x-environment: - &default-environment - LAGOON_PROJECT: *lagoon-project - # Route that should be used locally - LAGOON_ROUTE: http://drupal.docker.amazee.io - # Uncomment if you like to have the system behave like in production - #LAGOON_ENVIRONMENT_TYPE: production - # Uncomment to enable xdebug and then restart via `docker-compose up -d` - #XDEBUG_ENABLE: "true" - - -services: - - cli: # cli container, will be used for executing composer and any local commands (drush, drupal, etc.) - build: - context: . - dockerfile: Dockerfile.cli - image: *lagoon-project # this image will be reused as `CLI_IMAGE` in subsequent Docker builds - labels: - # Lagoon Labels - lagoon.type: cli-persistent - lagoon.persistent.name: nginx # mount the persistent storage of nginx into this container - lagoon.persistent: /app/web/sites/default/files/ # location where the persistent storage should be mounted - << : *default-volumes # loads the defined volumes from the top - volumes_from: # mount the ssh-agent from the pygmy or cachalot ssh-agent - - container:amazeeio-ssh-agent - environment: - << : *default-environment # loads the defined environment variables from the top - - nginx: - build: - context: . - dockerfile: Dockerfile.nginx - args: - CLI_IMAGE: *lagoon-project # Inject the name of the cli image - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - LAGOON_LOCALDEV_URL: nginx-drupal.docker.amazee.io # generate another route for nginx, by default we go to varnish - networks: - - amazeeio-network - - default - - php: - build: - context: . - dockerfile: Dockerfile.php - args: - CLI_IMAGE: *lagoon-project - labels: - lagoon.type: nginx-php-persistent - lagoon.name: nginx # we want this service be part of the nginx pod in Lagoon - lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - - - mariadb: - image: amazeeio/mariadb-drupal - labels: - lagoon.type: mariadb - ports: - - "3306" # exposes the port 3306 with a random local port, find it with `docker-compose port mariadb 3306` - environment: - << : *default-environment - - ## Uncomment for Redis - # redis: - # image: amazeeio/redis - # labels: - # lagoon.type: redis - # environment: - # << : *default-environment - - ## Uncomment for Solr - # solr: - # image: amazeeio/solr:6.6-drupal - # labels: - # lagoon.type: solr - # ports: - # - "8983" # exposes the port 8983 with a random local port, find it with `docker-compose port solr 8983` - # environment: - # << : *default-environment - - varnish: - image: amazeeio/varnish-drupal - labels: - lagoon.type: varnish - links: - - nginx # links varnish to the nginx in this docker-compose project, or it would try to connect to any nginx running in docker - environment: - << : *default-environment - VARNISH_BYPASS: "true" # by default we bypass varnish, change to 'false' or remove in order to tell varnish to cache if possible - networks: - - amazeeio-network - - default - -networks: - amazeeio-network: - external: true diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/drush/aliases.drushrc.php b/docs/using_lagoon/drupal/drupal8-composer-mariadb/drush/aliases.drushrc.php deleted file mode 100644 index 9c1679ab7..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/drush/aliases.drushrc.php +++ /dev/null @@ -1,19 +0,0 @@ - 'cache,cache_*,history,sessions,watchdog,feeds_log'); -$command_specific['sql-dump'] = array('structure-tables-list' => 'cache,cache_*,history,sessions,watchdog,feeds_log'); diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.services.yml b/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.services.yml deleted file mode 100644 index e6bb7c826..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.services.yml +++ /dev/null @@ -1,4 +0,0 @@ -### Lagoon Drupal 8 all environment services file. -# -# This file should contain service definitions that are needed on all environments -# diff --git a/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.settings.php b/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.settings.php deleted file mode 100755 index 88fa5fe7e..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-mariadb/web/sites/default/all.settings.php +++ /dev/null @@ -1,14 +0,0 @@ - 'mysql', - 'database' => getenv('MARIADB_DATABASE') ?: 'drupal', - 'username' => getenv('MARIADB_USERNAME') ?: 'drupal', - 'password' => getenv('MARIADB_PASSWORD') ?: 'drupal', - 'host' => getenv('MARIADB_HOST') ?: 'mariadb', - 'port' => 3306, - 'prefix' => '', - ); -} - -// Lagoon Solr connection -// WARNING: you have to create a search_api server having "solr" machine name at -// /admin/config/search/search-api/add-server to make this work. -if (getenv('LAGOON') && (file_exists($app_root . '/modules/contrib/search_api_solr') || file_exists($app_root . 'modules/search_api_solr'))) { - $config['search_api.server.solr']['backend_config']['connector_config']['host'] = (getenv('SOLR_HOST') ?: 'solr'); - $config['search_api.server.solr']['backend_config']['connector_config']['path'] = '/solr/'; - $config['search_api.server.solr']['backend_config']['connector_config']['core'] = (getenv('SOLR_CORE') ?: 'drupal'); - $config['search_api.server.solr']['backend_config']['connector_config']['port'] = 8983; - $config['search_api.server.solr']['backend_config']['connector_config']['http_user'] = (getenv('SOLR_USER') ?: ''); - $config['search_api.server.solr']['backend_config']['connector_config']['http']['http_user'] = (getenv('SOLR_USER') ?: ''); - $config['search_api.server.solr']['backend_config']['connector_config']['http_pass'] = (getenv('SOLR_PASSWORD') ?: ''); - $config['search_api.server.solr']['backend_config']['connector_config']['http']['http_pass'] = (getenv('SOLR_PASSWORD') ?: ''); - $config['search_api.server.solr']['name'] = 'Lagoon Solr - Environment: ' . getenv('LAGOON_PROJECT'); -} - -// Lagoon Redis connection if Drupal Redis module exists and PHP Redis Module is loaded. -if (getenv('LAGOON') && (file_exists($app_root . '/modules/contrib/redis') || file_exists($app_root . 'modules/redis')) && extension_loaded('redis')) { - $settings['redis.connection']['interface'] = 'PhpRedis'; - $settings['redis.connection']['host'] = getenv('REDIS_HOST') ?: 'redis'; - $settings['redis.connection']['port'] = 6379; - - $settings['cache_prefix']['default'] = getenv('LAGOON_PROJECT') . '_' . getenv('LAGOON_GIT_SAFE_BRANCH'); - - // Do not set the cache during installations of Drupal. - if (!drupal_installation_attempted()) { - $settings['cache']['default'] = 'cache.backend.redis'; - - // Include the default example.services.yml from the module, which will - // replace all supported backend services (that currently includes the cache tags - // checksum service and the lock backends, check the file for the current list) - $settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml'; - - // Allow the services to work before the Redis module itself is enabled. - $settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml'; - - // Manually add the classloader path, this is required for the container cache bin definition below - // and allows to use it without the redis module being enabled. - $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); - - // Use redis for container cache. - // The container cache is used to load the container definition itself, and - // thus any configuration stored in the container itself is not available - // yet. These lines force the container cache to use Redis rather than the - // default SQL cache. - $settings['bootstrap_container_definition'] = [ - 'parameters' => [], - 'services' => [ - 'redis.factory' => [ - 'class' => 'Drupal\redis\ClientFactory', - ], - 'cache.backend.redis' => [ - 'class' => 'Drupal\redis\Cache\CacheBackendFactory', - 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], - ], - 'cache.container' => [ - 'class' => '\Drupal\redis\Cache\PhpRedis', - 'factory' => ['@cache.backend.redis', 'get'], - 'arguments' => ['container'], - ], - 'cache_tags_provider.container' => [ - 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', - 'arguments' => ['@redis.factory'], - ], - 'serialization.phpserialize' => [ - 'class' => 'Drupal\Component\Serialization\PhpSerialize', - ], - ], - ]; - } -} - -// Trusted Host Patterns, see https://www.drupal.org/node/2410395 for more information. -// If your site runs on multiple domains, you need to add these domains here. -if (getenv('LAGOON_ROUTES')) { - $settings['trusted_host_patterns'] = array( - // Escape dots, remove schema, use commas as regex separator. - '^' . str_replace(['.', 'https://', 'http://', ','], ['\.', '', '', '|'], getenv('LAGOON_ROUTES')) . '$', - ); -} - -// Temp directory. -if (getenv('TMP')) { - $config['system.file']['path']['temporary'] = getenv('TMP'); -} - -// Hash Salt. -if (getenv('LAGOON')) { - $settings['hash_salt'] = hash('sha256', getenv('LAGOON_PROJECT')); -} - -// Settings for all environments. -if (file_exists(__DIR__ . '/all.settings.php')) { - include __DIR__ . '/all.settings.php'; -} - -// Services for all environments. -if (file_exists(__DIR__ . '/all.services.yml')) { - $settings['container_yamls'][] = __DIR__ . '/all.services.yml'; -} - -if (getenv('LAGOON_ENVIRONMENT_TYPE')) { - // Environment specific settings files. - if (file_exists(__DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php')) { - include __DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php'; - } - - // Environment specific services files. - if (file_exists(__DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.services.yml')) { - $settings['container_yamls'][] = __DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.services.yml'; - } -} - -// Last: this servers specific settings files. -if (file_exists(__DIR__ . '/settings.local.php')) { - include __DIR__ . '/settings.local.php'; -} -// Last: This server specific services file. -if (file_exists(__DIR__ . '/services.local.yml')) { - $settings['container_yamls'][] = __DIR__ . '/services.local.yml'; -} diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/.dockerignore b/docs/using_lagoon/drupal/drupal8-composer-postgres/.dockerignore deleted file mode 100644 index 1972606e6..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.git -vendor -web/sites/default/files diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/.gitignore b/docs/using_lagoon/drupal/drupal8-composer-postgres/.gitignore deleted file mode 100644 index 1ff7d25cb..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# Ignore directories generated by Composer -/drush/contrib/ -/vendor/ -/web/core/ -/web/modules/contrib/ -/web/themes/contrib/ -/web/profiles/contrib/ -/web/libraries/ - -# Ingore files that are only for the current local environment -web/sites/*/settings.local.php -web/sites/*/services.local.yml - -# Ignore Drupal's file directory -/web/sites/*/files/ - -# Ignore SimpleTest multi-site environment. -/web/sites/simpletest - -# Ignore files generated by PhpStorm -/.idea/ \ No newline at end of file diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/.lagoon.yml b/docs/using_lagoon/drupal/drupal8-composer-postgres/.lagoon.yml deleted file mode 100644 index 357966a86..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/.lagoon.yml +++ /dev/null @@ -1,26 +0,0 @@ -docker-compose-yaml: docker-compose.yml - -tasks: - post-rollout: - - run: - name: env variables - command: env - service: cli - - run: - name: drush cim - command: drush -y cim - service: cli - - run: - name: drush cr - command: drush -y cr - service: cli - - - -environments: - master: - # cronjobs: - # - name: drush cron - # schedule: "H * * * *" # this will run the cron once per Hour - # command: drush cron - # service: cli diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.cli b/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.cli deleted file mode 100644 index ffbe0b59c..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.cli +++ /dev/null @@ -1,11 +0,0 @@ -FROM amazeeio/php:7.2-cli-drupal - -COPY composer.json composer.lock /app/ -COPY scripts /app/scripts -# Uncomment if you have a patches directory in your Drupal Installation -# COPY patches /app/patches -RUN composer install --no-dev -COPY . /app - -# Define where the Drupal Root is located -ENV WEBROOT=web \ No newline at end of file diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.nginx b/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.nginx deleted file mode 100644 index 5b3c862b0..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.nginx +++ /dev/null @@ -1,9 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as builder - -FROM amazeeio/nginx-drupal - -COPY --from=builder /app /app - -# Define where the Drupal Root is located -ENV WEBROOT=web diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.php b/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.php deleted file mode 100644 index fc330309b..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/Dockerfile.php +++ /dev/null @@ -1,6 +0,0 @@ -ARG CLI_IMAGE -FROM ${CLI_IMAGE} as builder - -FROM amazeeio/php:7.2-fpm - -COPY --from=builder /app /app diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/docker-compose.yml b/docs/using_lagoon/drupal/drupal8-composer-postgres/docker-compose.yml deleted file mode 100644 index b2daba917..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/docker-compose.yml +++ /dev/null @@ -1,120 +0,0 @@ -version: '2.3' - -x-lagoon-project: - # Lagoon project name (leave `&lagoon-project` when you edit this) - &lagoon-project drupal-example - -x-volumes: - &default-volumes - # Define all volumes you would like to have real-time mounted into the docker containers - volumes: - - .:/app:delegated - -x-environment: - &default-environment - LAGOON_PROJECT: *lagoon-project - # Route that should be used locally - LAGOON_ROUTE: http://drupal.docker.amazee.io - # Uncomment if you like to have the system behave like in production - #LAGOON_ENVIRONMENT_TYPE: production - # Uncomment to enable xdebug and then restart via `docker-compose up -d` - #XDEBUG_ENABLE: "true" - - -services: - - cli: # cli container, will be used for executing composer and any local commands (drush, drupal, etc.) - build: - context: . - dockerfile: Dockerfile.cli - image: *lagoon-project # this image will be reused as `CLI_IMAGE` in subsequent Docker builds - labels: - # Lagoon Labels - lagoon.type: cli-persistent - lagoon.persistent.name: nginx # mount the persistent storage of nginx into this container - lagoon.persistent: /app/web/sites/default/files/ # location where the persistent storage should be mounted - << : *default-volumes # loads the defined volumes from the top - volumes_from: # mount the ssh-agent from the pygmy or cachalot ssh-agent - - container:amazeeio-ssh-agent - environment: - << : *default-environment # loads the defined environment variables from the top - - nginx: - build: - context: . - dockerfile: Dockerfile.nginx - args: - CLI_IMAGE: *lagoon-project # Inject the name of the cli image - labels: - lagoon.type: nginx-php-persistent - lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - LAGOON_LOCALDEV_URL: nginx.drupal.docker.amazee.io # generate another route for nginx, by default we go to varnish - networks: - - amazeeio-network - - default - - php: - build: - context: . - dockerfile: Dockerfile.php - args: - CLI_IMAGE: *lagoon-project - labels: - lagoon.type: nginx-php-persistent - lagoon.name: nginx # we want this service be part of the nginx pod in Lagoon - lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too - << : *default-volumes # loads the defined volumes from the top - depends_on: - - cli # basically just tells docker-compose to build the cli first - environment: - << : *default-environment # loads the defined environment variables from the top - - - postgres: - image: amazeeio/postgres-drupal - labels: - lagoon.type: postgres - ports: - - "5432" # exposes the port 3306 with a random local port, find it with `docker-compose port postgres 3306` - environment: - << : *default-environment - - ## Uncomment for Redis - # redis: - # image: amazeeio/redis - # labels: - # lagoon.type: redis - # environment: - # << : *default-environment - - ## Uncomment for Solr - # solr: - # image: amazeeio/solr:6.6-drupal - # labels: - # lagoon.type: solr - # ports: - # - "8983" # exposes the port 8983 with a random local port, find it with `docker-compose port solr 8983` - # environment: - # << : *default-environment - - varnish: - image: amazeeio/varnish-drupal - labels: - lagoon.type: varnish - links: - - nginx # links varnish to the nginx in this docker-compose project, or it would try to connect to any nginx running in docker - environment: - << : *default-environment - VARNISH_BYPASS: "true" # by default we bypass varnish, change to 'false' or remove in order to tell varnish to cache if possible - networks: - - amazeeio-network - - default - -networks: - amazeeio-network: - external: true diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/drush/aliases.drushrc.php b/docs/using_lagoon/drupal/drupal8-composer-postgres/drush/aliases.drushrc.php deleted file mode 100644 index 9c1679ab7..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/drush/aliases.drushrc.php +++ /dev/null @@ -1,19 +0,0 @@ - 'cache,cache_*,history,sessions,watchdog,feeds_log'); -$command_specific['sql-dump'] = array('structure-tables-list' => 'cache,cache_*,history,sessions,watchdog,feeds_log'); diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.services.yml b/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.services.yml deleted file mode 100644 index d167f7e61..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.services.yml +++ /dev/null @@ -1,4 +0,0 @@ -### amazee.io Drupal 8 all environment services file. -# -# This file should contain service definitions that are needed on all environments -# diff --git a/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.settings.php b/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.settings.php deleted file mode 100755 index 3ad880d08..000000000 --- a/docs/using_lagoon/drupal/drupal8-composer-postgres/web/sites/default/all.settings.php +++ /dev/null @@ -1,16 +0,0 @@ - 'pgsql', - 'database' => getenv('POSTGRES_DATABASE') ?: 'drupal', - 'username' => getenv('POSTGRES_USERNAME') ?: 'drupal', - 'password' => getenv('POSTGRES_PASSWORD') ?: 'drupal', - 'host' => getenv('POSTGRES_HOST') ?: 'postgres', - 'port' => 5432, - 'prefix' => '', - ); -} - -// Lagoon Solr connection -// // WARNING: you have to create a search_api server having "solr" machine name at -// // /admin/config/search/search-api/add-server to make this work. -// if (getenv('LAGOON')) { -// $config['search_api.server.solr']['backend_config']['connector_config']['host'] = (getenv('SOLR_HOST') ?: 'solr'); -// $config['search_api.server.solr']['backend_config']['connector_config']['path'] = '/solr/'; -// $config['search_api.server.solr']['backend_config']['connector_config']['core'] = (getenv('SOLR_CORE') ?: 'drupal'); -// $config['search_api.server.solr']['backend_config']['connector_config']['port'] = 8983; -// $config['search_api.server.solr']['backend_config']['connector_config']['http_user'] = (getenv('SOLR_USER') ?: ''); -// $config['search_api.server.solr']['backend_config']['connector_config']['http']['http_user'] = (getenv('SOLR_USER') ?: ''); -// $config['search_api.server.solr']['backend_config']['connector_config']['http_pass'] = (getenv('SOLR_PASSWORD') ?: ''); -// $config['search_api.server.solr']['backend_config']['connector_config']['http']['http_pass'] = (getenv('SOLR_PASSWORD') ?: ''); -// $config['search_api.server.solr']['name'] = 'Lagoon Solr - Environment: ' . getenv('LAGOON_PROJECT'); -// }. -// Lagoon Redis connection -// if (getenv('LAGOON')){ -// $settings['redis.connection']['interface'] = 'PhpRedis'; -// $settings['redis.connection']['host'] = getenv('REDIS_HOST') ?: 'redis'; -// $settings['redis.connection']['port'] = 6379; -// -// // HINT: Uncomment in order to enable Redis -// // # Do not set the cache during installations of Drupal -// // if (!drupal_installation_attempted()) { -// // $settings['cache']['default'] = 'cache.backend.redis'; -// // } -// }. -// Lagoon Varnish & Reverse proxy settings -// if (getenv('LAGOON')) { -// $settings['reverse_proxy'] = TRUE; -// }. -// Trusted Host Patterns, see https://www.drupal.org/node/2410395 for more information. -// If your site runs on multiple domains, you need to add these domains here. -if (getenv('LAGOON_ROUTES')) { - $settings['trusted_host_patterns'] = array( - // Escape dots, remove schema, use commas as regex separator. - '^' . str_replace(['.', 'https://', 'http://', ','], ['\.', '', '', '|'], getenv('LAGOON_ROUTES')) . '$', - ); -} - -// Temp directory. -if (getenv('TMP')) { - $config['system.file']['path']['temporary'] = getenv('TMP'); -} - -// Hash Salt. -if (getenv('LAGOON')) { - $settings['hash_salt'] = hash('sha256', getenv('LAGOON_PROJECT')); -} - -// Settings for all environments. -if (file_exists(__DIR__ . '/all.settings.php')) { - include __DIR__ . '/all.settings.php'; -} - -// Services for all environments. -if (file_exists(__DIR__ . '/all.services.yml')) { - $settings['container_yamls'][] = __DIR__ . '/all.services.yml'; -} - -if (getenv('LAGOON_ENVIRONMENT_TYPE')) { - // Environment specific settings files. - if (file_exists(__DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php')) { - include __DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.settings.php'; - } - - // Environment specific services files. - if (file_exists(__DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.services.yml')) { - $settings['container_yamls'][] = __DIR__ . '/' . getenv('LAGOON_ENVIRONMENT_TYPE') . '.services.yml'; - } -} - -// Last: this servers specific settings files. -if (file_exists(__DIR__ . '/settings.local.php')) { - include __DIR__ . '/settings.local.php'; -} -// Last: This server specific services file. -if (file_exists(__DIR__ . '/services.local.yml')) { - $settings['container_yamls'][] = __DIR__ . '/services.local.yml'; -} diff --git a/docs/using_lagoon/drupal/drush9.md b/docs/using_lagoon/drupal/drush9.md deleted file mode 100644 index 4188eb8d2..000000000 --- a/docs/using_lagoon/drupal/drush9.md +++ /dev/null @@ -1,47 +0,0 @@ -# Drush 9 - -Unfortunately Drush 9 does not provide the possibility to inject dynamic Site Aliases like Drush 8 did. We are working with the Drush team to implement this again. In the meantime we have a workaround that allows you to use Drush 9 with Lagoon. - -### Basic Idea - -Drush 9 provides a new command `drush site:alias-convert` which can convert Drush 8 style site aliases over to the Drush 9 yaml site alias style. This will create a one time export of the site aliases currently existing in Lagoon and save them within `/app/drush/sites` which then are used when running a command like `drush sa`. - -### Preparation - -In order to be able to use `drush site:alias-convert` you need to do the following: - -- rename the `aliases.drushrc.php` inside the `drush` folder to `lagoon.aliases.drushrc.php` - -### Generate Site aliases - -Now you can run the converting process: - -- `drush site:alias-convert` - -It's a good practice to commit the resulting yaml files into your git repo, so your fellow developers don't need to do the same all the time. - -### Use Site Aliases - -In Drush 9 all site aliases are prefixed with a group, in our case this is `lagoon`. You can show all site aliases with their prefix via: - -``` -drush sa --format=list -``` - -and to use them: `drush @lagoon.master ssh` - -### Update Site Aliases - -If a new environment in Lagoon has been created, you can just run `drush site:alias-convert` to update the site aliases file. - -### Drush rsync from local to remote environments - -If you like to sync files from a local to a remote environment you need to pass additional parameters: - -``` -drush rsync @self:%files @lagoon.master:%files -- --omit-dir-times --no-perms --no-group --no-owner --chmod=ugo=rwX -``` - -This is not necessary if you rsync from a remote to a local environment. - -Also we're [working with the Drush Maintainers](https://github.com/drush-ops/drush/issues/3491) to find a way to inject this fully automatically. diff --git a/docs/using_lagoon/drupal/first_deployment.md b/docs/using_lagoon/drupal/first_deployment.md deleted file mode 100644 index 2747fb881..000000000 --- a/docs/using_lagoon/drupal/first_deployment.md +++ /dev/null @@ -1,124 +0,0 @@ -# First Deployment of Drupal - -It's time! It's time for the first deployment into Lagoon! We hope you are as excited as we are! - -![excited](https://i.giphy.com/media/7kVRZwYRwF1ok/giphy-downsized.gif) - -## 1. Make sure you are all set - -In order to make your first deployment a successful one, please make sure that your [Drupal Project is Lagoonized](./lagoonize.md) and you have setup the Project in Lagoon. If not, don't worry, just follow the [Step-by-Step Guides](../index.md) which show you how this works. - -## 2. Push! - -With Lagoon you create a new deployment with just pushing into a branch that is configured to be deployed. - -If you don't have any new code to push, don't worry, just run - - git commit --allow-empty -m "go, go! Power Rangers!" - git push - -This will trigger a push and the Git Hosting should inform Lagoon about this push via the configured Webhook. - -If all is correct you should see a Notification in your configured Chat System: - -![Deployment in Slack Start](/images/first_deployment_slack_start.jpg) - -This is the information for you that Lagoon just started to deploy your code. Depending on the size of the code and amount of containers this will take a couple of seconds. Just relax. If you like to know whats happening now, check out the [Deployment & Build Process of Lagoon](../build_deploy_process.md) - -## 4. A fail - -Depending of your post rollout tasks inside `.lagoon.yml` you probably run some tasks like `drush updb` or `drush cr`. These Drush tasks depend on a Database existing within the environment, which obviously does not exist yet. Let's fix that: - -## 5. Synchronize local Database to the remote Lagoon environment - -With full Drush Site Aliases support in Lagoon it is super easy to synchronize a local database with the remote lagoon environment. - -First let's make sure that you can see the Drush Site Aliases: - - drush sa - -This should return your just deployed environment (let's assume you just pushed into `develop`): - - [drupal-example]cli-drupal:/app$ drush sa - @develop - @self - default - -*If you receive any error, it's most likely that your SSH Key is not added to the local container or not added to Lagoon, please check the Help Section of Drupal and Lagoon.* - -With this we can now synchronize the local database (which is represented in drush via the site alias `@self`) with the remote one (`@develop`): - - drush sql-sync @self @develop - -You should see something like: - - [drupal-example]cli-drupal:/app$ drush sql-sync @self @develop - You will destroy data in ssh.lagoon.amazeeio.cloud/drupal and replace with data from drupal. - Do you really want to continue? (y/n): y - Starting to dump database on Source. [ok] - Database dump saved to /home/drush-backups/drupal/20180227075813/drupal_20180227_075815.sql.gz [success] - Starting to discover temporary files directory on Destination. [ok] - You will delete files in drupal-example-develop@ssh.lagoon.amazeeio.cloud:/tmp/drupal_20180227_075815.sql.gz and replace with data from /home/drush-backups/drupal/20180227075813/drupal_20180227_075815.sql.gz - Do you really want to continue? (y/n): y - Copying dump file from Source to Destination. [ok] - Starting to import dump file onto Destination database. - -Now let's try another deployment, again just an empty push: - - git commit --allow-empty -m "go, go! Power Rangers!" - git push - -This time all should be green: - -![Deployment in Slack Success](/images/first_deployment_slack_2nd_success.jpg) - -Click on the Links and you should see your Drupal site loaded in all it's beauty, just most probably without pictures, this will be handled in Step 6. - -If it is still failing, check the `Logs` link for more information. - -## 6. Synchronize local files to the remote Lagoon environment - -You probably guessed it: It's super easy with Drush: - - drush rsync @self:%files @develop:%files - -It should show you something like: - - [drupal-example]cli-drupal:/app$ drush rsync @self:%files @develop:%files - You will delete files in drupal-example-develop@ssh.lagoon.amazeeio.cloud:/app/web/sites/default/files and replace with data from /app/web/sites/default/files/ - Do you really want to continue? (y/n): y - -In some cases though it looks not correct, like here: - - [drupal-example]cli-drupal:/app$ drush rsync @self:%files @develop:%files - You will delete files in drupal-example-develop@ssh.lagoon.amazeeio.cloud:'/app/web/%files' and replace with data from '/app/web/%files'/ - Do you really want to continue? (y/n): - -The reason for that is, that the Drupal cannot resolve the path of the files directory. This most probably has to do that the Drupal is not fully configured or has a missing Database. For an easy workaround you can use `drush rsync @self:sites/default/files @develop:sites/default/files` but we suggest to actually check your local and remote Drupal (you can test with `drush status` if the files directory is correctly configured). - - -## 7. It's done! - -As soon as Lagoon is done building and deploying it will send a second notification to the chat system, here an example: - -![Deployment in Slack Success](/images/first_deployment_slack_success.jpg) - -It tells you: - -- Which project has been deployed -- Which branch and Git sha has been deployed -- A link to the full Logs of the Build and Deployment -- Links to all Routes (URLs) where the environment can be reached at. - -That's it! We hope that wasn't too hard. - -## But wait, how about other branches or the production environment? - -That's the beauty of Lagoon: It's exactly the same: Just push the branchname you defined to be your production branch and that one will be deployed. - -## Failure? Don't worry. - -Did the deployment fail? Oh no! But we're here to help: - -1. Click on the `Logs` Link in the Error Notification, it will tell you where in the Deployment Process the failure happened. -2. If you can't figure it out, just ask your Lagoon Support, they are definitely here to help! diff --git a/docs/using_lagoon/drupal/lagoonize.md b/docs/using_lagoon/drupal/lagoonize.md deleted file mode 100644 index 0d40908ea..000000000 --- a/docs/using_lagoon/drupal/lagoonize.md +++ /dev/null @@ -1,139 +0,0 @@ -# Step by Step: Getting Drupal ready to run on Lagoon - -## 1. Lagoon Drupal Setting Files - -In order for Drupal to work with Lagoon we need to teach Drupal about Lagoon and Lagoon about Drupal. This happens with copying specific YAML and PHP Files into your Git Repository. - -You find these Files [here](https://github.com/amazeeio/lagoon/tree/master/docs/using_lagoon/drupal). The easiest way is to download them as [ZIP File](https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/amazeeio/lagoon/tree/master/docs/using_lagoon/drupal) and copy them into your Git Repository. For each Drupal Version and Database Type you will find an individual folder. A short overview of what they are: - -- `.lagoon.yml` - The main file that will be used by Lagoon to understand what should be deployed and many more things. This file has some sensible Drupal defaults, if you would like to edit or modify, please check the specific [Documentation for .lagoon.yml](/using_lagoon/lagoon_yml.md) -- `docker-compose.yml`, `.dockerignore` and `Dockerfile.*` - These files are used to run your Local Drupal Development environment, they tell docker which services to start and how to build them. They contain sensible defaults and many commented lines, it should be pretty much self describing. If you would like to find out more, see [Documentation for docker-compose.yml]() -- `sites/default/*` - These .php and .yml files teach Drupal how to communicate with Lagoon containers both locally and in production. It also provides an easy system for specific overrides in development and production environments. Unlike other Drupal hosting systems, Lagoon never ever injects Drupal Settings files into your Drupal. Therefore you can edit them to your wish. Like all other files they contain sensible defaults and some commented parts. -- `drush/aliases.drushrc.php` - These files are specific to Drush and tell Drush how to talk to the Lagoon GraphQL API in order to learn about all Site Aliases there are. -- `drush/drushrc.php` - Some sensible defaults for Drush Commands. -- Add `patches` directory if you choose [drupal8-composer-mariadb](https://github.com/amazeeio/lagoon/tree/master/docs/using_lagoon/drupal/drupal8-composer-mariadb). - -### Remark to `.gitignore` - -Don't forget to make sure your `.gitignore` will allow you to commit the settings files (Drupal is shipped with `sites/*/settings*.php` and `sites/*/services*.yml` in .gitignore, remove that, as with Lagoon we don't ever have sensitive information in the Git repository.) - -### Remark to Webroot in Drupal 8 - -Unfortunately the Drupal Community couldn't decide yet on a standardized webroot folder name. Some projects put Drupal within `web` others within `docroot` or somewhere else. The Lagoon Drupal Setting Files assume that your Drupal is within `web`, if this is different for your Drupal, please adapt the files accordingly. - -## 2. Customise docker-compose.yml - -Don't forget to customise the values in lagoon-project & LAGOON_ROUTE with your site specific name & the URL you'd like to access the site with: - -## 3. Build Images - -As next we need to build the defined images: - - docker-compose build - -This will tell docker-compose to build the Docker Images for all containers that have an `build:` definition in the `docker-compose.yml`. Usually for Drupal this is the case for the `cli`, `nginx` and `php`. We do this because we want to run specific Build commands (like `composer install`) or inject specific environment variables (like `WEBROOT`) into the Images. - -Usually building is not needed every time you edit your Drupal Code (as the Code is mounted into the Containers from your Host), but rebuilding does not hurt. -Plus Lagoon will build the exact same Docker Images also during a deploy, you can therefore check that your Build will also work during a deployment with just running `docker-compose build` again. - -## 4. Start Containers - -Now as the Images are built, we can start the Containers: - - docker-compose up -d - -This will bring up all containers. After the command is done, you can check with `docker-compose ps` if all of them are fully up and didn't crash yet. If there is a problem, check the logs with `docker-compose logs -f [servicename]`. - -If everything went well, open the `LAGOON_ROUTE` defined in `docker-compose.yml` (for example http://drupal.docker.amazee.io) and you should be greeted by a nice Drupal Error. Don't worry that's ok right now, most important is that it tries to load a Drupal site. - -## 5. Rerun `composer install` (for Composer projects only) - -In a local development environment you most probably open the Drupal Code in your favorite IDE and you also want all dependencies downloaded and installed, so connect into the cli container and run `composer install`: - - docker-compose exec cli bash - composer install - -This maybe sounds weird, as there was already a `composer install` executed during the Build step, let us explain: -- In order to be able to edit files on the Host and have them immediately available in the container, the default docker-composer.yml mounts the whole folder into the the containers (this happens with `.:/app:delegated` in the volumes section). This also means that all dependencies installed during the Docker build are overwritten with the files on the Host. -- Locally you probably want dependencies defined as `require-dev` in `composer.json` also existing, while on a production deployment they would just use unnecessary space. So we run `composer install --no-dev` in the Dockerfile and `composer install` manually. - -## 6. Check Status and Install Drupal - -Finally it's time to install a Drupal, but just before that we want to make sure everything works alright. We suggest to use Drush for that: - - docker-compose exec cli bash - drush status - -This should return something like: - - [drupal-example]cli-drupal:/app$ drush status - [notice] Missing database table: key_value - Drupal version : 8.6.1 - Site URI : http://drupal.docker.amazee.io - Database driver : mysql - Database hostname : mariadb - Database port : 3306 - Database username : drupal - Database name : drupal - PHP binary : /usr/local/bin/php - PHP config : /usr/local/etc/php/php.ini - PHP OS : Linux - Drush script : /app/vendor/drush/drush/drush - Drush version : 9.4.0 - Drush temp : /tmp - Drush configs : /home/.drush/drush.yml - /app/vendor/drush/drush/drush.yml - Drupal root : /app/web - Site path : sites/default - -Now it is time to install Drupal (if instead you would like to import an existing SQL File, please skip to step 6, but we suggest you install a clean Drupal in the beginning to be sure everything works.) - - drush site-install - -This should output something like: - - [drupal-example]cli-drupal:/app$ drush site-install - You are about to DROP all tables in your 'drupal' database. Do you want to continue? (y/n): y - Starting Drupal installation. This takes a while. Consider using the --notify global option. - Installation complete. User name: admin User password: a7kZJekcqh - Congratulations, you installed Drupal! - -Now you can visit the URL defined in `LAGOON_ROUTE` and you should see a fresh and clean installed Drupal - Congrats! - -![Congrats](https://media.giphy.com/media/XreQmk7ETCak0/giphy.gif) - -## 7. Import existing Database Dump - -If you have an already existing Drupal Site you probably want to import a database dump in your local site. - -There are many different ways on how to create a database dump, if your current hosting provider has Drush installed, you can use the following: - - drush sql-dump --result-file=dump.sql - - Database dump saved to dump.sql - - -Now you have a `dump.sql` file that contains your whole database. - -Copy this file into Git Repository and connect to the CLI, you should see the file in there: - - [drupal-example]cli-drupal:/app$ ls -l dump.sql - -rw-r--r-- 1 root root 5281 Dec 19 12:46 dump.sql - -Now you can import the Dump with before dropping the current database: - - drush sql-drop - - drush sql-cli < dump.sql - -Verify that everything works with visiting the URL of your Project. - -## 8. Drupal files directory - -A Drupal Site also consists of the files directory. As the whole folder is mounted into the Docker Containers, just add the files into the correct folder (probably `web/sites/default/files`, `sites/default/files` or something similar). - -## 9. Done! - -You are done. The Lagoon Team wishes Happy Drupaling! - -If you like to deploy your Drupal into Lagoon, follow the next Step: [Setup a new Project in Lagoon](../setup_project.md) diff --git a/docs/using_lagoon/drupal/services/mariadb.md b/docs/using_lagoon/drupal/services/mariadb.md deleted file mode 100644 index ffcdda9e5..000000000 --- a/docs/using_lagoon/drupal/services/mariadb.md +++ /dev/null @@ -1,38 +0,0 @@ -# MariaDB - -### Galera - -For improved reliability, MariaDB can be used in a cluster for production sites. -This example, when placed in `.lagoon.yml` will enable Galera on the -`production` branch. - -``` -environments: - production: - types: - mariadb: mariadb-galera -``` - -also you will need to change your service definition in your `docker-compose.yml` - -``` - mariadb: - image: amazeeio/mariadb-galera-drupal - labels: - lagoon.type: mariadb - ports: - - "3306" # exposes the port 3306 with a random local port, find it with `docker-compose port mariadb 3306` - environment: - << : *default-environment -``` - -It is recommended to configure the environment before the initial deploy of the -production site, otherwise manual intervention may be needed from your lagoon -administrator. - -### Additional MariaDB Logging - -During the course of development, it may be necessary to enable either query -logging or slow query logging. To do so just set the environment variables -`MARIADB_LOG_SLOW` or `MARIADB_LOG_QUERIES`. This can be done in -`docker-compose.yaml`. diff --git a/docs/using_lagoon/drupal/services/redis.md b/docs/using_lagoon/drupal/services/redis.md deleted file mode 100644 index 5d275802d..000000000 --- a/docs/using_lagoon/drupal/services/redis.md +++ /dev/null @@ -1,101 +0,0 @@ -# Redis - -We recommend using Redis for internal caching. Add the redis -service to `docker-compose.yaml`. - -``` - redis: - image: amazeeio/redis - labels: - lagoon.type: redis - << : *default-user # uses the defined user from top - environment: - << : *default-environment -``` - -Also, to configure redis, add the following to your `settings.php`. - - -### Drupal 7 -``` -if(getenv('LAGOON')){ - $conf['redis_client_interface'] = 'PhpRedis'; - $conf['redis_client_host'] = 'redis'; - $conf['lock_inc'] = 'sites/all/modules/contrib/redis/redis.lock.inc'; - $conf['path_inc'] = 'sites/all/modules/contrib/redis/redis.path.inc'; - $conf['cache_backends'][] = 'sites/all/modules/contrib/redis/redis.autoload.inc'; - $conf['cache_default_class'] = 'Redis_Cache'; - $conf['cache_class_cache_form'] = 'DrupalDatabaseCache'; - $conf['cache_class_cache_field'] = 'DrupalDatabaseCache'; -} -``` - -Depending on file system structure, the module paths may need to be updated. - -### Drupal 8 - -The Drupal 8 config is largely stock. Notably, redis is disabled while drupal is being installed. - -``` -if (getenv('LAGOON')){ - $settings['redis.connection']['interface'] = 'PhpRedis'; - $settings['redis.connection']['host'] = getenv('REDIS_HOST') ?: 'redis'; - $settings['redis.connection']['port'] = 6379; - $settings['cache_prefix']['default'] = getenv('LAGOON_PROJECT') . '_' . getenv('LAGOON_GIT_SAFE_BRANCH'); - - // Do not set the cache during installations of Drupal - if (!drupal_installation_attempted() && extension_loaded('redis')) { - $settings['cache']['default'] = 'cache.backend.redis'; - - // and allows to use it without the redis module being enabled. - $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); - - $settings['bootstrap_container_definition'] = [ - 'parameters' => [], - 'services' => [ - 'redis.factory' => [ - 'class' => 'Drupal\redis\ClientFactory', - ], - 'cache.backend.redis' => [ - 'class' => 'Drupal\redis\Cache\CacheBackendFactory', - 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], - ], - 'cache.container' => [ - 'class' => '\Drupal\redis\Cache\PhpRedis', - 'factory' => ['@cache.backend.redis', 'get'], - 'arguments' => ['container'], - ], - 'cache_tags_provider.container' => [ - 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', - 'arguments' => ['@redis.factory'], - ], - 'serialization.phpserialize' => [ - 'class' => 'Drupal\Component\Serialization\PhpSerialize', - ], - ], - ]; - } -} -``` - -### Persistent - -Redis can also be configured as a persistent backend. - -``` -redis: - image: amazeeio/redis-persistent - labels: - lagoon.type: redis-persistent - environment: - << : *default-environment -``` - -## Environment Variables -Environment variables are meant to do common behavior changes of redis. - -| Environment Variable | Default | Description | -| -----------------------| --------- | ---------------------------------------------- | -| `LOGLEVEL` | `notice` | Redis Loglevel | -| `DATABASES` | `1` | Number of Databases | -| `MAXMEMORY` | `100mb` | Maximum Memory usage of Redis | diff --git a/docs/using_lagoon/drupal/services/solr.md b/docs/using_lagoon/drupal/services/solr.md deleted file mode 100644 index 76a9a020a..000000000 --- a/docs/using_lagoon/drupal/services/solr.md +++ /dev/null @@ -1,46 +0,0 @@ -# Solr - -## Standard use - For Solr 5.5 and 6.6 we ship the default schema files provided by [search_api_solr](https://www.drupal.org/project/search_api_solr) version 8.x-1.2. Add the Solr version you would like to use in your docker-compose.yml file, following [our example](https://github.com/amazeeio/drupal-example/blob/master/docker-compose.yml#L103-L111) - -## Custom schema -To implement schema customizations for Solr in your project look to how Lagoon [creates our standard images](https://github.com/amazeeio/lagoon/blob/master/images/solr-drupal/Dockerfile). - -* In the `solr` section of your docker-compose file replace `image: amazeeio/solr:6.6` with: - -``` - build: - context: . - dockerfile: Dockerfile.solr -``` - -* Place your schema files in your code repository, we typically like to use `.lagoon/solr` -* Create a Dockerfile.solr - -``` -FROM amazeeio/solr:6.6 - -COPY .lagoon/solr /solr-conf/conf - -RUN precreate-core drupal /solr-conf - -CMD ["solr-foreground"] -``` - -The goal is to have your solr configuration files exist at `/solr-conf/conf` in the image you are building. - -## Multiple cores - -To implement multiple cores, you will also need to ship your own solr schema as above, the only change needed is to the `CMD` of the Dockerfile, repeat the pattern of `precreate-core corename /solr-conf/ ;` for each core you require. - -``` - -FROM amazeeio/solr:6.6-drupal - -RUN precreate-core drupal-index1 /solr-conf && \ - precreate-core drupal-index2 /solr-conf && \ - precreate-core drupal-index3 /solr-conf - -CMD ["solr-foreground"] - -``` diff --git a/docs/using_lagoon/drupal/services/varnish.md b/docs/using_lagoon/drupal/services/varnish.md deleted file mode 100644 index cfbd0d34e..000000000 --- a/docs/using_lagoon/drupal/services/varnish.md +++ /dev/null @@ -1,109 +0,0 @@ -# Varnish in Drupal - -We suggest to use Drupal with a Varnish reverse proxy. For this Lagoon provides a `varnish-drupal` Docker image that has Varnish already configured with a [Drupal Varnish Config](https://github.com/amazeeio/lagoon/blob/master/images/varnish-drupal/drupal.vcl). - -This Varnish Config does the following: -- It understands Drupal Session Cookies and automatically disables the Varnish caching for any authenticated request. -- It automatically caches any assets (images, css, js, etc.) for one month and also sends this header to the Browser, so Browser cache the assets as well. This happens for authenticated and non-authenticated requests. -- It has support for `BAN` and `URIBAN` which is used by the Drupal 8 purge module -- It removes `utm_` and `gclid` from the URL parameter to prevent that Google Analytics links cause multiple cache objects. -- And many other good things, just check out the [drupal.vcl](https://github.com/amazeeio/lagoon/blob/master/images/varnish-drupal/drupal.vcl) - -## Usage with Drupal 8 - -TL;DR: Check out the [Drupal 8 Example](https://github.com/amazeeio/drupal-example), it's shipped with the needed modules and needed Drupal configuration. - -### Install Purge and Varnish Purge modules - -In order to fully use Varnish with Drupal 8 Cache Tags, you need to install the [Purge](https://www.drupal.org/project/purge) and [Varnish Purge](https://www.drupal.org/project/varnish_purge) modules. They itself ship with many submodules, we suggest to install at least the following: `purge`, `purge_drush`, `purge_tokens`, `purge_ui`, `purge_processor_cron`, `purge_processor_lateruntime`, `purge_queuer_coretags`, `varnish_purger`, `varnish_purge_tags`. For the lacy ones: - - composer require drupal/purge drupal/varnish_purge - - drush en purge purge_drush purge_tokens purge_ui purge_processor_cron purge_processor_lateruntime purge_queuer_coretags varnish_purger varnish_purge_tags - -### Configure Varnish Purge - -1. Visit `Configuration > Development > Performance > Purge` -2. Add a purger via `Add purger` -3. Select `Varnish Bundled Purger` (not the `Varnish Purger`, see the #Behind the Scenes section, for more information.) -4. Click the dropdown beside the just added purger and click `Configure` -5. Give it a nice name, `Lagoon Varnish` sounds very good -6. Configure it with: - - TYPE: Tag - - REQUEST: - Hostname: varnish - (or whatever your Varnish is called in docker-compose.yml) - Port: 8080 - Path: / - Request Method: BAN - Scheme: http - - HEADERS: - Header: Cache-Tags - Value: [invalidations:separated_pipe] - -7. `Save configuration` - -That's it! If you like to test this locally, make sure you read the next section - -### Configure Drupal for Varnish - -There are a few other configurations that can be done: - -1. Uninstall the `Internal Page Cache` Drupal module with `drush pmu page_cache`. It can cause some weird double caching situations where only the Varnish cache is cleared but not the internal cache and changes appear very slowly to the users. Also it uses a lot of cache storage on big sites. -2. Change `$config['system.performance']['cache']['page']['max_age']` in `production.settings.php` to `2628000`. This tells Varnish to cache sites for up 1 month, which sounds maybe a bit a lot, but the Drupal 8 Cache Tag system is so awesome, that it will basically make sure that the varnish cache is purged whenever something changes. - -### Test Varnish Locally - -Drupal setups on Lagoon locally have Varnish and the Drupal Caches disabled as it can be rather hard to develop with all them set, this is done via: -- the `VARNISH_BYPASS=true` environment variable in `docker-compose.yml` which tells Varnish to basically disable itself -- Drupal is configured to not send any cache headers (via setting the Drupal Config `$config['system.performance']['cache']['page']['max_age'] = 0` in `development.settings.php`) - -To test Varnish locally, change the following in `docker-compose.yml` - -- set `VARNISH_BYPASS` to `false` in the varnish service section. -- set `LAGOON_ENVIRONMENT_TYPE` to `production` in the `x-environment` section -- run `docker-compose up -d` which restart all services with the new environment variables - -Now you should be able to test Varnish, here a short example assuming there is a node with the ID `1` and has the URL `drupal-example.docker.amazee.io/node/1` - -1. Run `curl -I drupal-example.docker.amazee.io/node/1` and look for these Headers: - - `X-LAGOON` should include `varnish` which tells you that the request actually went through `varnish` - - `Age:` will be still `0` as varnish probably never saw this site before and the first request will warm the varnish cache. - - `X-Varnish-Cache` will be `MISS` telling you as well that Varnish didn't find a previously cached version of this request. -2. Now run `curl -I drupal-example.docker.amazee.io/node/1` again and the Headers should now be: - - `Age:` will show you how many seconds ago the request has been cached, in our example it will probably something between 1-30, depending on how fast you are executing the command - - `X-Varnish-Cache` will be `HIT`, telling you that varnish successfully found a cached version of the request and returned that one to you. -3. Change the Node 1 in Drupal -4. Run `curl -I drupal-example.docker.amazee.io/node/1` and the Headers should be like on the very first request: - - `Age:0` - - `X-Varnish-Cache: MISS` - -### Varnish on Drupal behind the scenes - -If you come from other Drupal hosters or did for a Drupal 8 & Varnish tutorial before you might realized that there are a couple of changes in the Lagoon Drupal Varnish tutorial. Let's address them: - -#### Usage of `Varnish Bundled Purger` instead of `Varnish Purger` - -The `Varnish Purger` purger sends a `BAN` request for each single Cache-Tag that should be invalidated. Drupal has a lot of Cache-Tags and therefore this could lead into quite an amount of requests sent to Varnish. `Varnish Bundled Purger` instead sends just one `BAN` request for multiple invalidations, separated nicely by pipe (`|`) which fits perfectly to the varnish regular expression system of bans. This causes less requests and a less big ban list table inside Varnish. - -#### Usage of `Purge Late runtime processor` - -Contradictory to the Varnish Module in Drupal 7, the Drupal 8 Purge module has a slightly different approach to purging caches: It adds them to a queue which is then processed by different processors. Purge suggests to use the `Cron processor` which means that the varnish cache is only purged during a Cron run. This can lead into old data begin cached by Varnish, as probably your cron is not configured to run every minute or so, result are confused editors and clients. - -Instead we suggest to use the `Purge Late runtime processor`, which processes the queue at the end of each Drupal request. This has the advantage that if a Cache-Tag is added to the purge queue (like because an editor edited a Drupal Node) the Cache-Tags for this Node is directly purged. Together with the `Varnish Bundled Purger` this means just a single additional request to Varnish at the very end of a Drupal request, which causes no noticeable processing time on the request. - -#### Full support for Varnish Ban Lurker - -Our Varnish configurations have full support for Ban Lurker. Ban Lurker is basically a small tool that runs through the Varnish ban list and compares them to the cached requests in the varnish cache. If it finds one that should be "banned" it removes them from the cache and also removes the ban itself. This keeps the list of bans small and with that less processing time for Varnish on each request. - -### Troubleshooting - -Varnish doesn't cache? Or something else not working? Here a couple of ways to debug: - -- Run `drush p-debug-en` to enable debug logging of the purge module, this should show you debugging in the Drupal log under `admin/reports/dblog` -- Make sure that Drupal sends a proper cache headers. To test this best use the URL that Lagoon generates for bypassing the Varnish cache (locally in Drupal example this is http://nginx-drupal-example.docker.amazee.io). Check for an `Cache-Control: max-age=900, public` header, while the `900` is depending on what you configured in `$config['system.performance']['cache']['page']['max_age']` -- Make sure that the environment variable `VARNISH_BYPASS` is **not** set to `true` (see `docker-compose.yml` and run `docker-compose up -d varnish` to make sure the environment variable is configured correctly.) -- If all fails and before you flip your table, talk to the Lagoon Team, we're happy to help. diff --git a/docs/using_lagoon/environment_files.md b/docs/using_lagoon/environment_files.md deleted file mode 100644 index 5f0d32b6f..000000000 --- a/docs/using_lagoon/environment_files.md +++ /dev/null @@ -1,24 +0,0 @@ -#Environment Files - -It is common to store API Tokens or credentials for applications in environment variables. -Following best practices those credentials are different per environment. We allow each environment to use a separate -set of environment variables defined in Environment Files - -# `.env` and `.env.defaults` -`.env` and `.env.defaults` will act as the default values for environment variables if none other is defined. For example -as default environment variables for Pull-Request environments (see [Worfklows](./workflows.md#pull-requests)). - -# `.lagoon.env.$BRANCHNAME` -If you want to define environment variables different per environment you can create a `.lagoon.env.$BRANCHNAME` e.g. for the master branch `.lagoon.env.master`. This helps you keeping environment variables apart between environments. - -## Hierarchy of Environment Variables -We use a docker entrypoint ([50-dotenv.sh in the common image](https://github.com/amazeeio/lagoon/blob/master/images/commons/lagoon/entrypoints/50-dotenv.sh)) to read the environment files. - - -As there can already be environment variables defined in either the Dockerfile of during runtime (via docker run), we have an hierarchy of Environment variables: Environment variables defined in lower numbers are stronger - -1. Runtime environment variables (docker run) -2. environment variables defined in Dockerfile (ENV) -3. Env variables defined in `.lagoon.env.$BRANCHNAME` (if file exists and where $BRANCHNAME is the Branch this Dockerimage has been uilt for), use this for overwriting variables for only specific branches -4. Environment variables defined in `.env` -5. Environment variables defined in `.env.defaults` diff --git a/docs/using_lagoon/environment_types.md b/docs/using_lagoon/environment_types.md deleted file mode 100644 index 9c9c58e73..000000000 --- a/docs/using_lagoon/environment_types.md +++ /dev/null @@ -1,17 +0,0 @@ -# Environment Types - -Lagoon differentiates of currently two different Environment Types `production` and `development` - -When setting up your project via the Lagoon GraphQL API you can define a `productionEnvironment`. On every deployment Lagoon executes, it checks if the current environment name matches what is defined in `productionEnvironment` and if yes, it will mark this environment as the `production` environment. This happens in two locations: - -1. Within the GraphQL API itself -2. As an environment variable `LAGOON_ENVIRONMENT_TYPE` in every container - -But that's it. Lagoon itself handles `development` and `production` environments exactly the same (in the end we want as few differences of the environments as possible). - -There are a couple of things that will use this information: - -- If your Lagoon Administrator has idling enabled, non-production environments will automatically be idled after four hours of non usage (no worry, they are started automatically when you visit them). -- Our default Drupal settings.php files load additional settings files for `development.settings.php` and `production.settings.php` so you can define settings and configurations different per environment type. -- If you try to delete an environment that is defined as the production environment (either via Webhooks or REST) Lagoon will politely refuse to delete the production environment, as it tries to prevent you from making a mistake. In order to delete a production environment you can either change the `productionEnvironment` in the API or use the secret `forceDeleteProductionEnvironment: true` POST payload for the REST api. -- The Lagoon Administrator might use the production environment information for some additional things. Like at amazee.io we're calculating only the hits of the production environments to calculate the price of the hosting. diff --git a/docs/using_lagoon/first_deployment.md b/docs/using_lagoon/first_deployment.md deleted file mode 100644 index e588a36ba..000000000 --- a/docs/using_lagoon/first_deployment.md +++ /dev/null @@ -1,54 +0,0 @@ -# First Deployment - -It's time! It's time for the first deployment into Lagoon! We hope you are as excited as we are! - -![excited](https://i.giphy.com/media/7kVRZwYRwF1ok/giphy-downsized.gif) - -Also a short Heads-Up: If you are deploying a Drupal Project we suggest to read the [Drupal specific First Deployment Documentation](./drupal/first_deployment.md). - -## 1. Make sure you are all set - -In order to make your first deployment a successful one, please make sure that your Project is Lagoonized and you have setup the Project in Lagoon. If not, don't worry, just follow the [Step-by-Step Guides](./index.md) which show you how this works. - -## 2. Push! - -With Lagoon you create a new deployment with just pushing into a branch that is configured to be deployed. - -If you don't have any new code to push, don't worry, just run - - git commit --allow-empty -m "go, go! Power Rangers!" - git push - -This will trigger a push and the Git Hosting should inform Lagoon about this push via the configured Webhook. - -If all is correct you should see a Notification in your configured Chat System: - -![Deployment in Slack Start](/images/first_deployment_slack_start.jpg) - -This is the information for you that Lagoon just started to deploy your code. Depending on the size of the code and amount of containers this will take a couple of seconds. Just relax. If you like to know whats happening now, check out the [Deployment & Build Process of Lagoon](./build_deploy_process.md) - -## 3. It's done! - -As soon as Lagoon is done building and deploying it will send a second notification to the chat system, here an example: - -![Deployment in Slack Success](/images/first_deployment_slack_success.jpg) - -It tells you: -- Which project has been deployed -- Which branch and Git sha has been deployed -- A link to the full Logs of the Build and Deployment -- Links to all Routes (URLs) where the environment can be reached at. - -That's it! We hope that wasn't too hard. - -## But wait, how about other branches or the production environment? - -That's the beauty of Lagoon: It's exactly the same: Just push the branchname you defined to be your production branch and that one will be deployed. - -## Failure? Don't worry. - -Did the deployment fail? Oh no! But we're here to help: - -1. If you deployed a Drupal site, probably best read the [Drupal specific First Deployment Documentation](./drupal/first_deployment.md) which explains why this happens. -2. Click on the `Logs` Link in the Error Notification, it will tell you where in the Deployment Process the failure happened. -3. If you can't figure it out, just ask your Lagoon Support, they are definitely here to help! diff --git a/docs/using_lagoon/golive.md b/docs/using_lagoon/golive.md deleted file mode 100644 index 72eded3ae..000000000 --- a/docs/using_lagoon/golive.md +++ /dev/null @@ -1,92 +0,0 @@ -# Going Live - -Congratulations, you're close to going live with your website on lagoon! -In order to make this as seamless as possible this guide has been written. -It leads you trough the few things you should check before switching your site live. - - -## Check your .lagoon.yml - -### Routes / SSL -Check if all Routes have been setup in the `.lagoon.yml`. Be aware that as long as you don't point the Domains towards -lagoon you should disable Let's Encrypt (LE) certificate creation as it will lead to issues and Domains not pointing -towards lagoon will be disabled after a while in order to not exceed the Let's Encrypt quotas. - -If you use CA signed certificates you can set `tls-acme` to `false` but leave the `insecure` flag set to `Allow` or `Redirect`. -In the case of CA certificates let your lagoon administrator know the routes and the SSL certificate that needs to be put in place. - -``` -environments: - master: - routes: - - nginx: - - example.com - tls-acme: 'false' - insecure: Allow - - www.example.com: - tls-acme: 'false' - insecure: Allow -``` - -As soon as the DNS entries point towards your lagoon installation you can switch the flags: -`tls-acme` to `true` and `insecure` to `Redirect` - -``` -environments: - master: - routes: - - nginx: - - example.com - tls-acme: 'true' - insecure: Redirect - - www.example.com: - tls-acme: 'true' - insecure: Redirect -``` - -!!! hint - As checking every page of your website might get a bit a tedious job you can make use of mixed-content-scan. This will crawl the entire site and give you back Sites that include assets from a non-https site. - - -### Redirects -If you need non-www to www redirects make sure you have them setup in the `redirects-map.conf` - [see Documentation](https://lagoon.readthedocs.io/en/latest/using_lagoon/docker_images/nginx/#redirects-mapconf) - -### Cronjobs -Check if your cronjobs have been setup for your production environment - see [.lagoon.yml](lagoon_yml.md#environmentsnamecronjobs) - -## DNS -To make it as easy as possible for you to get your site pointing to our servers we have dedicated load balancer DNS records. Those technical DNS resource records are used just for getting your site linked to the amazee.io infrastructure and serve no other purpose. If you are in doubt of the CNAME record ask your lagoon administrator about the exact CNAME you need to setup. - -**Example on amazee.io :** `..amazee.io` - -Before you switch over your domain to lagoon make sure you lower the Time-to-Live (TTL) before the golive. This will ensure -that the switch from the old to the new servers will go fast and quick. We usually advise a TTL of 300-600 seconds prior -to the DNS Switch. [More information about TTL](https://en.wikipedia.org/wiki/Time_to_live#DNS_records) - -!!! warning - We do not suggest to configure any static IP address in your DNS Zones. As the lagoon loadbalancer infrastructure may change over time which can have impact on your site availability if you configured a static IP address. - - -### Root Domains -Configuring the root domain (e.g. example.com) can be a bit tricky because the DNS specification does not allow to have the root domain pointed to a CNAME entry. Depending on your DNS Provider the record name is different: - -- ALIAS at [DNSimple](https://dnsimple.com/) -- ANAME at [DNS Made Easy](http://www.dnsmadeeasy.com/) -- ANAME at [easyDNS](https://www.easydns.com/) -- ALIAS at [PointDNS](https://pointhq.com/) -- CNAME at [CloudFlare](https://www.cloudflare.com/) -- CNAME at [NS1](http://ns1.com) - -If your DNS Provider needs an IP address for the root domain - get in touch with your lagoon administrator to give you the load balancer IP addresses. - -## Production environment -Lagoon has the concept of development and production environments. Development environments automatically send `noindex` and `nofollow` -headers in order to prohibit indexing by search engines. - -``` X-Robots-Tag: noindex, nofollow``` - -During Project setup the production environment should already be defined. If that's ommited your environment will run in -development mode. You can check if the environment is set as production environment in the lagoon user interface. If the -production environment is ot set let your lagoon administrator know they will configure the system accordingly. - -![](../images/lagoon-ui-production.png) diff --git a/docs/using_lagoon/graphql_api.md b/docs/using_lagoon/graphql_api.md deleted file mode 100644 index ac7693369..000000000 --- a/docs/using_lagoon/graphql_api.md +++ /dev/null @@ -1,83 +0,0 @@ -# GraphQL API - -## Connect to GraphQL API - -API interactions in Lagoon are done via GraphQL, we suggest the [GraphiQL App](https://github.com/skevy/graphiql-app) to connect. In order to authenticate to the API, we also need a JWT (JSON Web Token) which will authenticate you against the API via your SSH Public Key. To generate such token, use the Remote Shell via the `token` command: - -```bash -ssh -p [PORT] -t lagoon@[HOST] token -``` - -Example for amazee.io: - -```bash -ssh -p 32222 -t lagoon@ssh.lagoon.amazeeio.cloud token -``` - -This will return you with a long string, which is the jwt token. - -We also need the URL of the API Endpoint, ask your Lagoon Administrator for this. On amazee.io this is https://api.lagoon.amazeeio.cloud/graphql - -Now we need a GraphQL client, technically this is just HTTP, but there is a nice UI that allows you to write GraphQL requests with autocomplete. Download, install and start it. - -Enter the API Endpoint URL. Then click on "Edit HTTP Headers" and add a new Header: - -* "Header name": `Authorization` -* "Header value": `Bearer [jwt token]` (make sure that the jwt token has no spaces, as this would not work) - -Close the HTTP Header overlay (press ESC) and now we are ready to make the first GraphQL Request! - -Enter this on the left window: - -```GraphQL -query whatIsThere { - allProjects { - id - gitUrl - name - branches - pullrequests - productionEnvironment - environments { - name - environmentType - } - } -} -``` - -And press the Play button (or press CTRL+ENTER). If all went well, you should see your first GraphQL response. - -## Mutations - -The Lagoon GraphQL API cannot only display Objects and create Objects, it also has the capability to update existing Objects, all of this happens in full GraphQL best practices manner. - -Update the branches to deploy within a project: - -```GraphQL -mutation editProjectBranches { - updateProject(input:{id:109, patch:{branches:"^(prod|stage|dev|update)$"}}) { - id - } -} -``` - -Update the production Environment within a project (Important: Needs a redeploy in order for all changes to be reflected in the containers): - -```GraphQL -mutation editProjectProductionEnvironment { - updateProject(input:{id:109, patch:{productionEnvironment:"master"}}) { - id - } -} -``` - -You can also combine multiple changes into a single query: - -```GraphQL -mutation editProjectProductionEnvironmentAndBranches { - updateProject(input:{id:109, patch:{productionEnvironment:"master", branches:"^(prod|stage|dev|update)$"}}) { - id - } -} -``` diff --git a/docs/using_lagoon/index.md b/docs/using_lagoon/index.md deleted file mode 100644 index 7ee375e10..000000000 --- a/docs/using_lagoon/index.md +++ /dev/null @@ -1,62 +0,0 @@ -# Use Lagoon - -## Requirements - -### Docker - -To run Lagoon Project your system must meet the requirements to run Docker. We suggest installing the latest version of Docker for your workstation. You can download Docker [here](https://www.docker.com/get-docker). We also suggest allowing Docker at least **4 CPUs** and **4GB RAM**. - -### Local Development Environments - -TL;DR: install and start `pygmy`: - - gem install pygmy - pygmy up - -Learn more about Lagoon and [Local Development Environments](./local_development_environments.md) - -## Step by Step Guides - -- Drupal: [Lagoonize your Drupal Site](./drupal/lagoonize.md) -- [Setup a new Project in Lagoon](./setup_project.md) -- General: [First Deployment](./first_deployment.md) -- Drupal: [First Deployment Drupal](./drupal/first_deployment.md) -- [Deployment & Build Process of Lagoon](./build_deploy_process.md) - -## Overview of Lagoon Configuration Files - -### `.lagoon.yml` - -They main file that will be used by Lagoon to understand what should be deployed and many more things. See [Documentation for .lagoon.yml](/using_lagoon/lagoon_yml.md) - -### `docker-compose.yml` - -This file is used by Docker Compose to start you Local Development environment. Lagoon also uses it to understand which of the Services should be deployed, which type and how to build them. This happens via `labels`. See [Documentation for docker-compose.yml](/using_lagoon/docker-compose_yml.md) - -### Dockerfiles - -Some Docker Images and Containers need additional customizations from the provided Images, this usually has two reasons: -1. Application code: Containers like Nginx, PHP, Node, etc. need the actual programming code within their Images. This is done during a Docker Build step which are configured in Dockerfiles. Lagoon has full support for Docker and therefore also allows you full control over the resulting Images via Dockerfile customizations. -2. Customization of Images: Lagoon also allows you to customize the base Images according to your needs. This can be to inject an additional environment variable, change a service configuration or even install additional tools, even though we advise caution with installing additional tools to the Docker Images, as such adaptions need to be maintained by yourself in the future! - -## Supported Services & Base Images by Lagoon - -| Type | Versions | Dockerfile | -| ---------------| -------------------| -------------------------------------------------------------------------------------------------------------| -| nginx | openresty/1.13.6.2 | [nginx/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/nginx/Dockerfile) | -| nginx-drupal | | [nginx-drupal/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/nginx-drupal/Dockerfile) | -| [php-fpm](docker_images/php-fpm.md) | 7.1, 7.2, 7.3 | [php/fpm/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/php/fpm/Dockerfile) | -| php-cli | 7.1, 7.2, 7.3 | [php/cli/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/php/cli/Dockerfile) | -| php-cli-drupal | 7.1, 7.2, 7.3 | [php/cli-drupal/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/php/cli-drupal/Dockerfile) | -| mariadb | 10 | [mariadb/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/mariadb/Dockerfile) | -| mariadb-drupal | 10 | [mariadb-drupal/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/mariadb-drupal/Dockerfile) | -| mongo | 3.6 | [mongo/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/mongo/Dockerfile) | -| solr | 5.5, 6.6, 7.5 | [solr/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/solr-drupal/Dockerfile) | -| solr-drupal | 5.5, 6.6, 7.5 | [solr-drupal/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/solr-drupal/Dockerfile)| -| redis | 5.0.0 | [redis/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/redis/Dockerfile) | -| redis-persistent | 5.0.0 | [redis-persistent/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/redis-persistent/Dockerfile) | -| varnish | 5 | [varnish/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/varnish/Dockerfile) | -| varnish-drupal | 5 | [varnish-drupal/Dockerfile](https://github.com/amazeeio/lagoon/blob/master/images/varnish-drupal/Dockerfile) | - -All images are pushed to https://hub.docker.com/u/amazeeio. -We suggest to always use the latest tag (like `amazeeio/nignx:latest`) or unsuffixed images (like `amazeeio/node:10`), as they are kept up to date in terms of features and security. If you shall choose to use a specific Lagoon Version of an image like `amazeeio/nignx:v0.21.0` or `amazeeio/node:10-v0.21.0` it is your own responsibility to upgrade the version of the Images as soon as a new Lagoon Version is released! diff --git a/docs/using_lagoon/lagoon_yml.md b/docs/using_lagoon/lagoon_yml.md deleted file mode 100644 index f97d96a75..000000000 --- a/docs/using_lagoon/lagoon_yml.md +++ /dev/null @@ -1,255 +0,0 @@ -# .lagoon.yml file -The `.lagoon.yml` is the central file to setup your project: - -* define pre-rollout tasks -* define post-rollout tasks -* set up SSL certificates -* add cronjobs for environments -* define routes for accessing your sites - -The `.lagoon.yml` file must be placed at the root of your git repository. - -## Example `.lagoon.yml` - -``` -docker-compose-yaml: docker-compose.yml - -environment_variables: - git_sha: 'true' - -tasks: - pre-rollout: - - run: - name: drush sql-dump - command: mkdir -p /app/web/sites/default/files/private/ && drush sql-dump --ordered-dump --gzip --result-file=/app/web/sites/default/files/private/pre-deploy-dump.sql.gz - service: cli - post-rollout: - - run: - name: drush cim - command: drush -y cim - service: cli - shell: bash - - run: - name: drush cr - command: drush -y cr - service: cli - -routes: - insecure: Redirect - -environments: - master: - monitoring_urls: - - "www.example.com" - - "www.example.com/special_page" - routes: - - nginx: - - example.com - - example.net - - "www.example.com": - tls-acme: 'true' - insecure: Redirect - hsts: max-age=31536000 - cronjobs: - - name: drush cron - schedule: "H * * * *" # this will run the cron once per Hour - command: drush cron - service: cli - staging: - cronjobs: - - name: drush cron - schedule: "H * * * *" # this will run the cron once per Hour - command: drush cron - service: cli -``` -## General Settings - -##### `docker-compose-yaml` -Tells the build script which docker-compose yaml file should be used in order to learn which services and containers should be deployed. This defaults to `docker-compose.yml` but could be used for a specific lagoon docker-compose yaml file if you need something like that. - -#### `routes.autogenerate.generate` -This allows you to disable the automatic created routes (NOT the custom routes per environment, see below for them) all together. - -#### `routes.autogenerate.insecure` -This allows you to define the behaviour of the automatic creates routes (NOT the custom routes per environment, see below for them). You can define: - -* `Allow` simply sets up both routes for http and https (this is the default). -* `Redirect` will redirect any http requests to https -* `None` will mean a route for http will _not_ be created, and no redirect - -### `environment_variables.git_sha` -This setting allows you to enable injecting the deployed git SHA into your project as an environment variable. By default this is disabled, setting the value to `true` then sets the SHA as the environment variable `LAGOON_GIT_SHA`. - -## Tasks - -There are different type of tasks you can define, they differ when exactly they are executed in a build flow: - -### `pre_rollout.[i].run` -The task defined as `pre_rollout` tasks will run against your project _after_ the new images have been built successfully and _before_ the project gets altered in any way. -This feature enables you for example to create a database dump before the rollout is running. This will make it easier to roll-back in case of an issue with the rollout. - -#### `post_rollout.[i].run` -Here you can specify tasks which need to run against your project, _after_: - -- all Images have been successfully built -- all Containers are updated with the new Images -- all Containers are running have passed their readiness checks - -Common uses are to run `drush updb`, `drush cim`, or clear various caches. - -* `name` - - The name is an arbitrary label for making it easier to identify each task in the logs -* `command` - - Here you specify what command should run. These are run in the WORKDIR of each container, for Lagoon images this is `/app`, keep this in mind if you need to `cd` into a specific location to run your task. -* `service` - - The service which to run the task in. If following our drupal-example, this will be the CLI container, as it has all your site code, files, and a connection to the DB. Typically you do not need to change this. -* `shell` - - Which shell should be used to run the task in. By default `sh` is used, but if the container also has other shells (like `bash`, you can define it here). This is useful if you want to run some small if/else bash scripts within the post-rollouts. (see the example above how to write a script with multiple lines) - -## Environments -Environment names match your deployed branches or pull requests, it allows you for each environment to have a different config, in our example it will apply to the `master` and `staging` environment. - -#### `environments.[name].routes` -In the route section we identify the domain names which the environment will respond to. It is typical to only have an environment with routes specified for your production environment. All environments receive a generated route, but sometimes there is a need for a non-production environment to have it's own domain name, you can specify it here, and then add that domain with your DNS provider as a CNAME to the generated route name (these routes publish in deploy messages). - -The first element after the environment is the target service, `nginx` in our example. This is how we identify which service incoming requests will be sent to. - -The simplest route is the `example.com` example above. This will assume that you want a Let's Encrypt certificate for your route and no redirect from https to http. - -In the `"www.example.com"` example, we see two more options (also see the `:` at the end of the route and that the route is wrapped in `"`, that's important!): - -* `tls-acme: 'true'` tells Lagoon to issue a Let's Encrypt certificate for that route, this is the default. If you don't like a Let's Encrypt set this to `tls-acme: 'false'` -* `insecure` can be set to `None`, `Allow` or `Redirect`. - * `Allow` simply sets up both routes for http and https (this is the default). - * `Redirect` will redirect any http requests to https - * `None` will mean a route for http will _not_ be created, and no redirect will take place -* `hsts` can be set to a value of `max-age=31536000;includeSubDomains;preload`. Ensure there are no spaces and no other parameters included. Only `max-age` parameter is required. The required `max-age` parameter indicates the length of time, in seconds, the HSTS policy is in effect for. - -#### `environments.[name].cronjobs` -As most of the time it is not desirable to run the same cronjobs across all environments, you must explicitly define which jobs you want to run for each environment. - -* `name:` - * Just a friendly name for identifying what the cronjob will do -* `schedule:` - * The schedule at which to execute the cronjob. This follows the standard convention of cron. If you're not sure about the syntax [Crontab Generator](https://crontab-generator.org/) can help. - * You can specify `M` for the minute, and your cronjob will run once per hour at a random minute (the same minute each hour), or `M/15` to run it every 15 mins but with a random offset from the hour (like `6,21,36,51`) - * You can specify `H` for the hour, and your cronjob will run once per day at a random hour (the same hour every day) or `H(2-4)` to run it once per day within the hours of 2-4 -* `command:` - * The command to execute. Like the tasks, this executes in the WORKDIR of the service, for Lagoon images this is `/app` -* `service:` - * Which service of your project to run the command in. For most projects this is the `cli` service. - -#### `environments.[name].types` -The Lagoon Build processes checks the `lagoon.type` label from the `docker-compose.yml` file in order to learn what type of service should be deployed. - -Sometime though you would like to override the type just for a single environment and not for all of them, like if you want a mariadb-galera high availability database for your production environment called `master`: - -`service-name: service-type` - -* `service-name` - is the name of the service from `docker-compose.yml` you would like to override -* `service-type` - the type of the service you would like the service to override to. - -Example: - -``` -environments: - master: - types: - mariadb: mariadb-galera -``` - -#### `environments.[name].templates` -The Lagoon Build processes checks the `lagoon.template` label from the `docker-compose.yml` file in order to check if the service needs a custom template file (read more about them in the [documentation of `docker-compose.yml`](/using_lagoon/docker-compose_yml/#custom-templates)) - -Sometimes though you would like to override the template just for a single environment and not for all of them: - -`service-name: template-file` - -* `service-name` - is the name of the service from `docker-compose.yml` you would like to override -* `template-file` - the path and name of the template to use for this service in this environment - -Example: - -``` -environments: - master: - templates: - mariadb: mariadb.master.deployment.yaml -``` - -#### `environments.[name].rollouts` -The Lagoon Build processes checks the `lagoon.rollout` label from the `docker-compose.yml` file in order to check if the service needs a special rollout type (read more about them in the [documentation of `docker-compose.yml`](/using_lagoon/docker-compose_yml/#custom-deploymentconfig-templates)) - -Sometimes though you would like to override the rollout type just for a single environment, especially if you also overwrote the template type for the environment - -`service-name: rollout-type` - -* `service-name` - is the name of the service from `docker-compose.yml` you would like to override -* `rollout-type` - the type of rollout, see [documentation of `docker-compose.yml`](/using_lagoon/docker-compose_yml/#custom-rollout-monitor-types)) for possible values - -Example: - -``` -environments: - master: - rollouts: - mariadb: statefulset -``` - -#### `environments.[name].monitoring_urls` -At the end of a deplpoy, Lagoon will check this field for any URLs which you specify to add to the API for the purpose of monitoring. The default value for this field is the first route for a project. It is useful for adding specific paths of a project to the API, for consumption by a monitoring service. Please note, Lagoon does not provide any direct integration to a monitoring service, this just adds the URLs to the API. On amazee.io, we take the monitoring_urls and add them to our Statuscake account. - -## Polysite - -In Lagoon, the same git repository can be added to multiple projects, creating what is called a Polysite. This allows you to run the same codebase but allow for different, isolated, databases and persistent files. In `.lagoon.yml` we currently only support specifying custom routes for a polysite project. The key difference from a standard project is that the `environments` becomes the second-level element, and the project name the top level. - -Example: - -``` -example-project-name: - environments: - master: - routes: - - nginx: - - example.com -``` - -## Specials - -#### `api` -**Note:** If you run directly on amazee.io you will not need this key set. - -With the key `api` you can define another URL that should be used by `lagu` and `drush` to connect to the Lagoon GraphQL `api`. This needs to be a full URL with a scheme, like: `http://localhost:3000` -This usually does not need to be changed, but there might be situations where your Lagoon Administrator tells you to do so. - -#### `ssh` -**Note:** If you run directly on amazee.io you will not need this key set. - -With the key `ssh` you can define another SSH endpoint that should be used by `lagu` and `drush` to connect to the Lagoon Remote Shell service. This needs to be a hostname and a port separated by a colon, like: `localhost:2020` -This usually does not need to be changed, but there might be situations where your Lagoon Administrator tells you to do so. - - -#### `additional-yaml` - -The `additional-yaml` has a bit of super powers. Basically it allows you to create any arbitrary yaml configuration before during the build step (it still needs to be a valid kubernetes/openshift yaml though ;) ). - -Example: - -``` -additional-yaml: - secrets: - path: .lagoon.secrets.yaml - command: create - ignore_error: true - - logs-db-secrets: - path: .lagoon.logs-db-secrets.yaml - command: create - ignore_error: true -``` - -Each definition is keyed by a unique name (`secrets` and `logs-db-secrets` in the example above), and takes these keys: - -* `path` - the path to the yaml file -* `command` - can either be `create` or `apply`, depending on if you like to run `kubectl create -f [yamlfile]` or `kubectl apply -f [yamlfile]` -* `ignore_error` - either `true` or `false` (default), this allows you to instruct the lagoon build script to ignore any errors that might are returned during running the command. (This can be useful to handle the case where you want to run `create` during every build, so that eventual configurations are created, but don't want to fail if they already exist). diff --git a/docs/using_lagoon/local_development_environments.md b/docs/using_lagoon/local_development_environments.md deleted file mode 100644 index 937964a80..000000000 --- a/docs/using_lagoon/local_development_environments.md +++ /dev/null @@ -1,14 +0,0 @@ -# Local Development Environments - -Even though Lagoon has only a hard dependency on Docker and Docker Compose (which is mostly shipped with Docker) some things that are nice for local development are not included in Docker: - -- a HTTP Reverse Proxy for nice URLs and HTTPs offloading -- DNS System so we don't have to remember IP Addresses -- SSH Agents to use SSH keys within Containers -- a system that receives and displays mails locally - -Lagoon currently works best with `pygmy` which is the amazee.io flavored system of the above tools and works out of the box with Lagoon: - -`pygmy` is a Ruby gem, so simply `gem install pygmy`. For detailed usage info on `pygmy`, see the [documentation of pygmy](https://pygmy.readthedocs.io/) - -We are evaluating adding support for other systems like Lando, Docksal, DDEV, and Docker4Drupal, and will possibly add full support for these in the future. If you do have Lagoon running with a system like these, we would gladly love you to submit a [PR on Github](https://github.com/amazeeio/pygmy). diff --git a/docs/using_lagoon/logging.md b/docs/using_lagoon/logging.md deleted file mode 100644 index aa66e29ca..000000000 --- a/docs/using_lagoon/logging.md +++ /dev/null @@ -1,37 +0,0 @@ -# Logging - -Lagoon provides access to the following logs via Kibana: - -- Logs from the OpenShift Routers, including every single HTTP and HTTPs Request with: - - Source IP - - URL - - Path - - HTTP Verb - - Cookies - - Headers - - User Agent - - Project - - Container name - - Response Size - - Response Time -- Logs from Containers - - stdout and stderr messages - - Container name - - Project -- Lagoon Logs - - Webhooks parsing - - Build Logs - - Build Errors - - Any other Lagoon related Logs -- Application Logs - - Any Logs sent by the running application - - For Drupal: Install [Lagoon Logs](https://www.drupal.org/project/lagoon_logs) module in order to receive Logs from Drupal Watchdog - - -To access the Logs, please check with your Lagoon Administrator to get the URL for the Kibana Route (for amazee.io this is ). - -Each Lagoon Account has their own Login and will see the Logs only for the projects that they have access to. - -Also each Account has their own Kibana Tenant, which means no saved searches or visualizations are shared with another Account. - -If you like to know more on how to use Kibana: diff --git a/docs/using_lagoon/migrations/amazeeio.md b/docs/using_lagoon/migrations/amazeeio.md deleted file mode 100644 index 385e4116b..000000000 --- a/docs/using_lagoon/migrations/amazeeio.md +++ /dev/null @@ -1,59 +0,0 @@ -# Migration from amazee.io - -If you are migrating from the amazee.io Legacy infrastructure over to Lagoon you will feel very familiar with everything. In the end, the same brains are behind both projects. There are some changes though and this will explain you each of them. - -## Migration - -The migration itself will be done by the amazee.io team, we have fully automated migration scripts and will release them soon, until then: Lean back and let the amazee.io team do that work for you :) - -## Pygmy required, migrate from cachalot. - -Lagoon local development environments are built for `pygmy`, which itself is based on Docker for Mac/Windows. There have been great performance improvements in the last months and we feel comfortable migrating everybody to `pygmy`. `pygmy` can run the Legacy and Lagoon projects at the same time. - -If you are already using `pygmy`, then you can skip this. Here's how to migrate from `cachalot` to `pygmy`: - -1. Make sure that you have all local code committed and all local databases and files synced. There is, unfortunately, no way to migrate the databases over to pygmy, so make sure that there is nothing you will be sad about if it is gone. -2. Remove cachalot VM: `cachalot destroy` -3. Uninstall cachalot: `gem uninstall cachalot` (maybe needs sudo) -4. Remove an eventual `eval $(cachalot env)` from `~/.bash_profile`, `~/.zshrc` or `~/.config/fish/config.fish` -5. Follow the `pygmy` installation process: http://lagoon.readthedocs.io/en/latest/using_lagoon/#requirements - -## New services/containers in `docker-compose.yml` - -If you look at a `docker-compose.yml` which is shipped with a Lagoon project you will see that it grew a bit in size. This is because Lagoon uses containers for each service individually, which is much better for extensibility and future proof-ness. If you want to have a look, see the `docker-compose.yml` of [drupal-example](https://github.com/amazeeio/drupal-example/blob/mariadb/docker-compose.yml). - -## New `.lagoon.yml` file - -Instead of an `.amazeeio.yml` file, Lagoon projects now are mostly configured via a `.lagoon.yml` file. Overall it's purpose is very similar to the `.amazeeio.yml` file, but it has some new cool features: - -- Post-rollout tasks -- Custom Cronjobs -- Custom Routes -- and many more - -See http://lagoon.readthedocs.io/en/latest/using_lagoon/#lagoonyml for more (WIP currently) - -## Rename of `before_deploy` and `after_deploy` plus their location has moved - -Lagoon has a new definition of Build and Post-Rollout tasks: - -- Build tasks are defined in Dockerfiles and should be used for tasks that do not require connections to other services (like databases or so), they are therefore the new `before_deploy` tasks. Build tasks will profit from well-written Dockerfiles and will be sped up by Docker Layer Caching -- Post-Rollout tasks are executed after the old running containers have been replaced by the new ones created by the deployment. They can be used for any tasks that need access to other services, like a cache clear of the CMS. These tasks are therefore the old `after_deploy` tasks. -- With the Legacy hosting system, we had `development` and `production` tasks for `before_deploy` and `after_deploy`. We believe this was a mistake and caused some issues we never had really the same system of development and production. With the new Lagoon system it is technically still possible to have different build or post-rollout tasks based on the environment type (aka `development` and `production`) or the branch name, but we don't suggest to use that too much, as it can cause again weird situations where something might work on development but not on production. - -## Drush is still the same - -You can use `drush sql-sync @remote @self` like you are used to, also `drush @remote ssh` still works the same. - -## Everything is always in `/app` - -With the Legacy system the absolute path of the files was different for every environment, like `/var/www/drupal-example_master/public_html` and `/var/www/drupal-example_develop/public_html`. This is now resolved and your files will always be in `/app` no matter on which server or which environment you are. - -## New Environment Variables - -As Lagoon is a fully open source project and is actually does not want too many ties to amazee.io itself, we renamed all Environment variables. The new settings.php files will automatically reflect that, but if you are interested to have a look at the settings.php of the drupal-example: https://github.com/amazeeio/drupal-example/blob/master/web/sites/default/settings.php - -## Non-predictable user ids - -Lagoon is based on OpenShift and OpenShift puts one thing very high: Security. Not only is each project completely encapsulated in its own virtual network, each container is also run with a random user id. This brings much higher security as a possible attacker cannot know the ID of the user during a Docker Build step. -On the other side, this makes development a bit harder as we still want writable persistent storage, so OpenShift runs the container with a known Group ID: 1 (root). This gives the container access to the files that have been written by previous containers but doesn't actually give you root access inside the container. diff --git a/docs/using_lagoon/remote_shell.md b/docs/using_lagoon/remote_shell.md deleted file mode 100644 index 735e92232..000000000 --- a/docs/using_lagoon/remote_shell.md +++ /dev/null @@ -1,63 +0,0 @@ -# Remote Shell - -Lagoon allows you to connect into your running containers via SSH. The containers itself actually don't have any SSH Server installed, instead you connect via SSH to a Lagoon Service which then itself creates a remote shell connection via the Kubernetes API for you. - -### Endpoint - -Ask your Lagoon Administrator for the Lagoon SSH Host and Port. For amazee.io this `ssh.lagoon.amazeeio.cloud` and `32222`. - -### Authentication - -As you connect via SSH, the Authentication also happens automatically via SSH Public & Private Key Authentication (passwordless FTW!) - -### Connection - -Connecting is easy and follows the following pattern: - -``` -ssh -p [PORT] -t [PROJECT-ENVIRONMENT-NAME]@[HOST] rsh -``` - -- `PORT` - The Remote Shell SSH Endpoint Port (for amazee.io `32222`) -- `HOST` - The Remote Shell SSH Endpoint Host (for amazee.io `ssh.lagoon.amazeeio.cloud`) -- `PROJECT-ENVIRONMENT-NAME` - the environment you like to connect too, this is most commonly in the pattern `PROJECTNAME-ENVIRONMENT` - -As en example: - -``` -ssh -p 32222 -t drupal-example-master@ssh.lagoon.amazeeio.cloud rsh -``` - -Will connect you to the Project `drupal-example` on the environment `master`. - -### Pod/Service, Container Definition - -By default the remote shell will try to connect you to the container defined with the type `cli`. If you like to connect to another pod/service you can define it via - -``` -ssh -p [PORT] -t [PROJECT-ENVIRONMENT-NAME]@[HOST] rsh service=[SERVICE-NAME] -``` - -If your Pod/Service contains multiple containers, Lagoon will connect you to the first defined container. Or you can define the specific container via - -``` -ssh -p [PORT] -t [PROJECT-ENVIRONMENT-NAME]@[HOST] rsh service=[SERVICE-NAME] container=[CONTAINER-NAME] -``` - -As example to connect to the `php` container within the `nginx` pod: - -``` -ssh -p 32222 -t drupal-example-master@ssh.lagoon.amazeeio.cloud rsh service=nginx container=php -``` - -### Execute Commands - -Like with regular SSH you can also execute a remote command directly without opening an actual shell. - -Example: - -``` -ssh -p 32222 -t drupal-example-master@ssh.lagoon.amazeeio.cloud rsh whoami -``` - -Will execute `whoami` within the `cli` container. diff --git a/docs/using_lagoon/service_types.md b/docs/using_lagoon/service_types.md deleted file mode 100644 index e6b001199..000000000 --- a/docs/using_lagoon/service_types.md +++ /dev/null @@ -1,29 +0,0 @@ -# Service Types - -This table lists all service types that can be defined via `lagoon.type` within a [`docker-compose.yml` file](/using_lagoon/docker-compose_yml.md) - -| Type | Description | Healtcheck | Exposed Ports | Auto generated routes | Additional customization parameters | -| ---------------| -----------------------------------------------------|-----------------|-------|-------------| ---------------------------------------------------| -| `cli` | Use for any kind of CLI container (like PHP, Node, etc.). Automatically gets the customer ssh private key mounted in `/var/run/secrets/lagoon/sshkey/ssh-privatekey` | - | - | -| -| `cli-persistent` | Like `cli`, just expects `lagoon.persistent.name` given with the name of a service that has persistent storage which will be mounted under defined `lagoon.persistent` label. Does NOT generate it's own persistent storage, only used to mount another service's persistent storage | - | - | `lagoon.persistent.name`, `lagoon.persistent` | -| `nginx` | Nginx container. No persistent storage | `localhost:50000/nginx_status` | `8080` | yes | - | -| `nginx-php` | Like `nginx`, but additionally a `php` container. | nginx: `localhost:50000/nginx_status`, php: `/usr/sbin/check_fcgi` | `8080` | yes | - | -| `nginx-php-persistent` | Like `nginx-php`, will generate persistent storage, define mount location via `lagoon.persistent` | nginx: `localhost:50000/nginx_status`, php: `/usr/sbin/check_fcgi` | http on `8080` | yes | `lagoon.persistent`, `lagoon.persistent.name`, `lagoon.persistent.size`, `lagoon.persistent.class` | -| `mariadb` | A meta service which will tell lagoon to automatically decide between `mariadb-single` and `mariadb-shared` | - | - | - | - | -| `mariadb-single` | MariaDB container. Creates cronjob for Backups running every 24h executing `/lagoon/mysql-backup.sh 127.0.0.1` | TCP connection on `3306` | `3306` | - | `lagoon.persistent.size` | -| `mariadb-shared` | Uses a shared mariadb server via a mariadb service broker | not needed | `3306` | - | - | -| `mariadb-galera` | MariaDB Galera Cluster with 3 nodes, uses Statefulset, generates persistent storage for each Cluster node. Creates cronjob for Backups running every 24h executing `/lagoon/mysql-backup.sh 127.0.0.1`. Starts additional maxscale container where the service points to (no direct connection to galera nodes) | TCP connection on `3306` | `3306` | - | `lagoon.persistent.size` | -| `postgres` | Postgres container. Creates cronjob for Backups running every 24h executing `/lagoon/postgres-backup.sh localhost` | TCP connection on `5432` | `5432` | - | `lagoon.persistent.size` | -| `redis` | Redis container. | TCP connection on `6379` | `6379` | - | - | -| `solr` | Solr container with auto generated persistent storage mounted under `/opt/solr/server/solr/mycores`. | TCP connection on `8983` | `8983` | - | - | -| `varnish` | Varnish container. | HTTP request `localhost:8080/varnish_status` | `8080` | yes | - | -| `node` | Nodejs container. | TCP connection on `3000` | `3000` | yes | - | -| `node-persistent` | Like `node`, will generate persistent storage, define mount location via `lagoon.persistent` | TCP connection on `3000` | `3000` | yes | `lagoon.persistent`, `lagoon.persistent.name`, `lagoon.persistent.size`, `lagoon.persistent.class` | -| `mongo` | MongoDB container, will generate persistent storage of min 1GB mounted at `/data/db` | TCP connection on `27017` | `27017` | - | - | -| `mongo-shared` | Uses a shared mongodb server via a service broker | not needed | `27017` | - | - | -| `kibana` | Kibana container. | TCP connection on `5601` | `5601` | yes | - | -| `logstash` | Logstash container. | TCP connection on `9600` | `9600` | - | - | -| `elasticsearch` | Elasticsearch container, will auto generate persistent storage under `/usr/share/elasticsearch/data` | HTTP on `localhost:9200/_cluster/health?local=true` | `9200` | - | `lagoon.persistent.size` | -| `elasticsearch-cluster` | Elasticsearch Cluster with 3 nodes, users Statefulset, will auto generate persistent storage for each cluster node under `/usr/share/elasticsearch/data` | HTTP on `localhost:9200/_cluster/health?local=true` | `9200`, `9300` | - | - | -| `none` | Instructs Lagoon to completely ignore this service | - | - | - | - | -| `custom` | Full custom definition, see [documentation](./docker-compose_yml.md) | - | - | - | - | diff --git a/docs/using_lagoon/setup_project.md b/docs/using_lagoon/setup_project.md deleted file mode 100644 index 14a4a1aa4..000000000 --- a/docs/using_lagoon/setup_project.md +++ /dev/null @@ -1,36 +0,0 @@ -# Step by Step: Setup a new Project in Lagoon - -> **NOTE: We are working hard on getting a CLI and GraphQL API ready for everyone using Lagoon to setup and configure their projects themselves. We just need a little bit longer to test it before making the CLI and API publicly available.** - -Until then the setup of a new project involves talking to your Lagoon Administrator. Anyway, they are anyway much friendlier than APIs ;) - -Please have the following information ready for your Lagoon Administrator: - -- SSH Public Keys, email addresses and the names of everybody that will work on this project -- The URL of the Git repository where your code is hosted (`git@example.com:test/test.git`) -- The name of the Git branch you would like to use for your production environment (see [Environment Types](./environment_types.md)) -- Which Branches and Pull Requests you would like to deploy to your additional environments. With Lagoon you can filter Branches by their name with regular expressions, and Pull Requests by title again with regular expressions. - -We suggest that you deploy specific important Branches (like `develop` and `master`) and Pull Requests. But that's all up to how you would like it. (see [Workflows](workflows.md)) - -## 1. Make sure your project is Lagoonized - -We assume that your project is already lagoonized, this means that the `.lagoon.yml` and `docker-compose.yml` files are available in your Git repository and configured accordingly. - -If this is not the case, check out the list of [Step-by-Step Guides](./index.md) on how to do so. - -## 2. Provide access to your code - -In order to deploy your Code, Lagoon needs access to it. By design and for security Lagoon only needs read access to your Git Repository. - -Your Lagoon Administrator will tell you the SSH Public Key or the Git Account to give read access to. - -## 3. Configure Webhook - -Lagoon needs to be informed about a couple of events that are happening to your Git Repository. Currently these are Pushes and Pull Requests, but we may add more in the future. - -As Lagoon supports many different Git hosts, we have split off those instructions into this documentation: [Configure Webhooks](./configure_webhooks.md) - -## 4. Next: First deployment - -Congratulations, you are now ready to run your [first deployment](./first_deployment.md). diff --git a/docs/using_lagoon/workflows.md b/docs/using_lagoon/workflows.md deleted file mode 100644 index 3ef5bf3a2..000000000 --- a/docs/using_lagoon/workflows.md +++ /dev/null @@ -1,94 +0,0 @@ -# Workflows - -Lagoon tries to support any development workflow possible, it specifically does not enforce any workflows onto the teams, so that each development team can define how they would like to develop and deploy their code. - -### Fixed Branches - -The most obvious and easiest workflow are deployment based on some fixed branches: - -You define which branches (like `develop`, `staging` and `master`, which would be `^(develop|staging|master)$` as regular expression) that Lagoon should deploy and it will do so. Easy as pie! - -If you like to test a new feature, just merge them into a branch that you have setup locally and push, Lagoon will deploy the feature and you can test. When all is good, merge the branch into your production branch and push. - - -### Feature Branches - -A bit advanced are feature branches. As Lagoon supports to define the branches you would like to deploy via regular expression definitions, you can also extend the above regular expression to this: `^feature\/|^(staging|master)$`, this will instruct Lagoon to deploy also all branches that start with `feature/`, plus the branches called `staging` and `master`. Our development workflow could be as following: - -- Create a new branch from `master` called `feature/myfeature` and push `feature/myfeature` -- Lagoon will deploy the branch `feature/myfeature` as a new environment, where you can test your feature independently of any other features. -- Merge `feature/myfeature` into the `master` branch and it will deploy your production environment. - -If you like you can also merge `feature/myfeature` and any other feature branches first into `staging` in order to have a so called integration branch, to test the functionality of multiple features together. After you have tested the features together on staging, you can merge the features into master. - -This workflow needs a high cleanliness of branches on the Git Hosting, as each feature branch will create it's own Lagoon environment, you can have very fast a LOT of environments, which all of them will use resources. - -Therefore it could make sense to think about a Pull Request based workflow: - - -### Pull Requests - -Even more advanced are workflows via Pull Requests. Such workflows need the support of a Git Hosting which supports Pull Requests (or also called Merge Requests). The idea of Pull Request based workflows lies behind that idea that you can test a feature together with a target branch, without actually needing to merge yet, as Lagoon will do the merging for you during the build. - -In our example we would configure Lagoon to deploy the branches: `^(staging|master)$` and the Pull Requests to `.*` (basically to deploy all pull requests). Now the workflow would be: - -- Create a new branch from `master` called `feature/myfeature` and push `feature/myfeature` (no deployment will happen now) -- Create a Pull Request in your Git Hosting from `feature/myfeature` into `master` -- Lagoon will now merge the `feature/myfeature` branch merged on top of the `master` branch and deploy that resulting code for you -- Now you can test the functionality of the `feature/myfeature` branch like it would already have been merged into `master`, so all changes that have happened in `master` since you create the `feature/myfeature` branch from it will be there and you don't need to worry that you might have an older version of the `master` branch. -- After you have confirmed that everything works like you want it, you can go back to your Git Hosting and actually merge the code into `master`, this will now trigger a deployment of `master`. -- With the merge of the Pull Request it is automatically closed and Lagoon will remove the environment for the pull request fully automatically. - -Some teams might opt in to create the Pull Request against a shared `staging` branch and then merge the `staging` branch into the `master` branch via another Pull Request. - -Additionally in Lagoon you can define that only Pull Request with a specific text in the title are deployed. Like `[BUILD]` defined as regular expression, will only deploy Pull Requests that have a title like `[BUILD] My Pull Request`, while a Pull Request with that title `My other Pull Request` is not automatically deployed. This helps to keep the amount of environments small and allows for Pull Requests that don't need an environment yet. - -#### Automatic Database Sync for Pull Requests - -Automatic Pull Request environments are a fantastic thing. But it would also be handy to have the Database synced from another environment. - -Following example will sync the staging database on the first rollout of the Pull Request environment: -``` -tasks: - post-rollout: - - run: - name: IF no Drupal installed & Pullrequest = Sync database from staging - command: | - if [[ -n ${LAGOON_PR_BASE_BRANCH} ]] && ! drush status --fields=bootstrap | grep -q "Successful"; then - drush -y sql-sync @staging default - fi - service: cli - shell: bash -``` - -### Promotion - -Another way of deploying your code into an environment is the Promotion Workflow. The idea behind the promotion workflow comes from the fact that even if you merge (as an example) the branch `staging` into the `master` branch and it there where no changes in `master` before, so `master` and `staging` have the exact same code in the git repository, it could still technically be possible that the resulting Docker Images are slightly different, this comes from the fact that between the last `staging` deployment and the current `master` deployment maybe some upstream Docker Images have changed or dependencies loaded from the various package managers have changed. This is a very small chance, but it's there. - -For this Lagoon has the understanding of promoting Lagoon Images from one environment to another. Which basically means that it will take the already built and deployed Docker Images from one environment and will use the exact same Docker Images for another environment. - -In our example we want to promote the docker images from `master` environment to the environment `production`: - -- First we need a regular deployed environment with the name `master`, make sure that the deployment successfully ran through. -- Also make sure that you don't have a branch `production` in your Git Repository, as this could lead into weird confusions (like people pushing into this branch, etc.). -- Now trigger a promotion deployment via this curl request: - - curl -X POST \ - https://rest.lagoon.amazeeio.cloud/promote \ - -H 'Content-Type: application/json' \ - -d '{ - "projectName":"myproject", - "sourceEnvironmentName": "master", - "branchName": "production" - }' - - This defines, that you like to promote from the source `master` to the destination `production` (yes it really uses `branchName` as destination, which is a bit unfortunate, but this is gonna be fixed soon.) - -Lagoon will now do the following: - -- Checkout the Git branch `master` in order to load the `.lagoon.yml` and `docker-compose.yml` (Lagoon still needs these in order to fully work) -- Create all Kubernetes/OpenShift objects for the defined services in `docker-compose.yml` but with `LAGOON_GIT_BRANCH=production` as environment variable -- Copy the newest Images from the `master` environment and use them (instead of building Images or tagging them from upstream) -- Run all post-rollout tasks like a normal deployment - -You will receive the same notifications success or failures like any other deployment. diff --git a/flow-typed/custom/emit.js b/flow-typed/custom/emit.js deleted file mode 100644 index 468de6aeb..000000000 --- a/flow-typed/custom/emit.js +++ /dev/null @@ -1,4 +0,0 @@ -declare var emit: ( - a: string | Array | Object, - b: string | Array | Object -) => void; diff --git a/flow-typed/custom/execa_v0.10.x.js b/flow-typed/custom/execa_v0.10.x.js deleted file mode 100644 index 72525902e..000000000 --- a/flow-typed/custom/execa_v0.10.x.js +++ /dev/null @@ -1,104 +0,0 @@ -// flow-typed signature: 37dcb37211059702e08eaa203a3aa600 -// flow-typed version: f9d703bc84/execa_v0.10.x/flow_>=v0.75.x - -declare module 'execa' { - - declare type StdIoOption = - | 'pipe' - | 'ipc' - | 'ignore' - | 'inherit' - | stream$Stream - | number; - - declare type CommonOptions = {| - argv0?: string, - cleanup?: boolean, - cwd?: string, - detached?: boolean, - encoding?: string, - env?: {[string]: string}, - extendEnv?: boolean, - gid?: number, - killSignal?: string | number, - localDir?: string, - maxBuffer?: number, - preferLocal?: boolean, - reject?: boolean, - shell?: boolean | string, - stderr?: ?StdIoOption, - stdin?: ?StdIoOption, - stdio?: 'pipe' | 'ignore' | 'inherit' | $ReadOnlyArray, - stdout?: ?StdIoOption, - stripEof?: boolean, - timeout?: number, - uid?: number, - windowsVerbatimArguments?: boolean, - |}; - - declare type SyncOptions = {| - ...CommonOptions, - input?: string | Buffer, - |}; - - declare type Options = {| - ...CommonOptions, - input?: string | Buffer | stream$Readable, - |}; - - declare type SyncResult = {| - stdout: string, - stderr: string, - message?: string, - code: number, - failed: boolean, - signal: ?string, - cmd: string, - timedOut: boolean, - |}; - - declare type Result = {| - ...$Exact, - killed: boolean, - |}; - - // declare interface ThenableChildProcess extends child_process$ChildProcess { - // then( - // onfulfilled?: ?((value: Result) => R | Promise), - // onrejected?: ?((reason: ExecaError) => E | Promise), - // ): Promise; - - // catch( - // onrejected?: ?((reason: ExecaError) => E | Promise) - // ): Promise; - // } - - declare interface ExecaError extends ErrnoError { - stdout: string; - stderr: string; - failed: boolean; - signal: ?string; - cmd: string; - timedOut: boolean; - } - - declare interface Execa { - [[call]](file: string, args?: $ReadOnlyArray, options?: Options): Promise; - [[call]](file: string, options?: Options): Promise; - - stdout(file: string, args?: $ReadOnlyArray, options?: Options): Promise; - stdout(file: string, options?: Options): Promise; - - stderr(file: string, args?: $ReadOnlyArray, options?: Options): Promise; - stderr(file: string, options?: Options): Promise; - - shell(command: string, options?: Options): Promise; - - sync(file: string, args?: $ReadOnlyArray, options?: SyncOptions): SyncResult; - sync(file: string, options?: SyncOptions): SyncResult; - - shellSync(command: string, options?: Options): SyncResult; - } - - declare module.exports: Execa; -} diff --git a/flow-typed/custom/express_v4.16.x.js b/flow-typed/custom/express_v4.16.x.js deleted file mode 100644 index f4533ac25..000000000 --- a/flow-typed/custom/express_v4.16.x.js +++ /dev/null @@ -1,315 +0,0 @@ -// flow-typed signature: 106bbf49ff0c0b351c95d483d617ffba -// flow-typed version: 7fe23c8e85/express_v4.16.x/flow_>=v0.32.x - -import type { Server } from "http"; -import type { Socket } from "net"; - -declare type express$RouterOptions = { - caseSensitive?: boolean, - mergeParams?: boolean, - strict?: boolean -}; - -declare class express$RequestResponseBase { - app: express$Application; - get(field: string): string | void; -} - -declare type express$RequestParams = { - [param: string]: string -}; - -declare class express$Request extends http$IncomingMessage mixins express$RequestResponseBase { - baseUrl: string; - body: mixed; - cookies: { [cookie: string]: string }; - connection: Socket; - fresh: boolean; - hostname: string; - ip: string; - ips: Array; - method: string; - originalUrl: string; - params: express$RequestParams; - path: string; - protocol: "https" | "http"; - query: { [name: string]: string | Array }; - route: string; - secure: boolean; - signedCookies: { [signedCookie: string]: string }; - stale: boolean; - subdomains: Array; - xhr: boolean; - accepts(types: string): string | false; - accepts(types: Array): string | false; - acceptsCharsets(...charsets: Array): string | false; - acceptsEncodings(...encoding: Array): string | false; - acceptsLanguages(...lang: Array): string | false; - header(field: string): string | void; - is(type: string): boolean; - param(name: string, defaultValue?: string): string | void; -} - -declare type express$CookieOptions = { - domain?: string, - encode?: (value: string) => string, - expires?: Date, - httpOnly?: boolean, - maxAge?: number, - path?: string, - secure?: boolean, - signed?: boolean -}; - -declare type express$Path = string | RegExp; - -declare type express$RenderCallback = ( - err: Error | null, - html?: string -) => mixed; - -declare type express$SendFileOptions = { - maxAge?: number, - root?: string, - lastModified?: boolean, - headers?: { [name: string]: string }, - dotfiles?: "allow" | "deny" | "ignore" -}; - -declare class express$Response extends http$ServerResponse mixins express$RequestResponseBase { - headersSent: boolean; - locals: { [name: string]: mixed }; - append(field: string, value?: string): this; - attachment(filename?: string): this; - cookie(name: string, value: string, options?: express$CookieOptions): this; - clearCookie(name: string, options?: express$CookieOptions): this; - download( - path: string, - filename?: string, - callback?: (err?: ?Error) => void - ): this; - format(typesObject: { [type: string]: Function }): this; - json(body?: mixed): this; - jsonp(body?: mixed): this; - links(links: { [name: string]: string }): this; - location(path: string): this; - redirect(url: string, ...args: Array): this; - redirect(status: number, url: string, ...args: Array): this; - render( - view: string, - locals?: { [name: string]: mixed }, - callback?: express$RenderCallback - ): this; - send(body?: mixed): this; - sendFile( - path: string, - options?: express$SendFileOptions, - callback?: (err?: ?Error) => mixed - ): this; - sendStatus(statusCode: number): this; - header(field: string, value?: string): this; - header(headers: { [name: string]: string }): this; - set(field: string, value?: string | string[]): this; - set(headers: { [name: string]: string }): this; - status(statusCode: number): this; - type(type: string): this; - vary(field: string): this; - req: express$Request; -} - -// Lagoon addition: extend Error to have status property (for auth-server) -declare interface express$LagoonErrorWithStatus extends Error { - status: number; -} - -declare type express$NextFunction = (err?: ?Error | "route") => mixed; -declare type express$Middleware = - | (( - req: $Subtype, - res: express$Response, - next: express$NextFunction - ) => mixed) - | (( - // Lagoon change: extend Error to have status property (for auth-server). Original: - // error: Error, - error: express$LagoonErrorWithStatus, - req: $Subtype, - res: express$Response, - next: express$NextFunction - ) => mixed); -declare interface express$RouteMethodType { - (middleware: express$Middleware): T; - (...middleware: Array): T; - ( - path: express$Path | express$Path[], - ...middleware: Array - ): T; -} -declare class express$Route { - all: express$RouteMethodType; - // Lagoon change: Type relaxed to allow for modifying the context. (for api) - // Original: - // get: express$RouteMethodType; - get: Function; - post: express$RouteMethodType; - put: express$RouteMethodType; - head: express$RouteMethodType; - delete: express$RouteMethodType; - options: express$RouteMethodType; - trace: express$RouteMethodType; - copy: express$RouteMethodType; - lock: express$RouteMethodType; - mkcol: express$RouteMethodType; - move: express$RouteMethodType; - purge: express$RouteMethodType; - propfind: express$RouteMethodType; - proppatch: express$RouteMethodType; - unlock: express$RouteMethodType; - report: express$RouteMethodType; - mkactivity: express$RouteMethodType; - checkout: express$RouteMethodType; - merge: express$RouteMethodType; - - // @TODO Missing 'm-search' but get flow illegal name error. - - notify: express$RouteMethodType; - subscribe: express$RouteMethodType; - unsubscribe: express$RouteMethodType; - patch: express$RouteMethodType; - search: express$RouteMethodType; - connect: express$RouteMethodType; -} - -declare class express$Router extends express$Route { - constructor(options?: express$RouterOptions): void; - route(path: string): express$Route; - static (options?: express$RouterOptions): express$Router; - use(middleware: express$Middleware): this; - use(...middleware: Array): this; - use( - path: express$Path | express$Path[], - ...middleware: Array - ): this; - use(path: string, router: express$Router): this; - handle( - req: http$IncomingMessage, - res: http$ServerResponse, - next: express$NextFunction - ): void; - param( - param: string, - callback: ( - req: $Subtype, - res: express$Response, - next: express$NextFunction, - id: string - ) => mixed - ): void; - ( - req: http$IncomingMessage, - res: http$ServerResponse, - next?: ?express$NextFunction - ): void; -} - -/* -With flow-bin ^0.59, express app.listen() is deemed to return any and fails flow type coverage. -Which is ironic because https://github.com/facebook/flow/blob/master/Changelog.md#misc-2 (release notes for 0.59) -says "Improves typings for Node.js HTTP server listen() function." See that? IMPROVES! -To work around this issue, we changed Server to ?Server here, so that our invocations of express.listen() will -not be deemed to lack type coverage. -*/ - -declare class express$Application extends express$Router mixins events$EventEmitter { - constructor(): void; - locals: { [name: string]: mixed }; - mountpath: string; - listen( - port: number, - hostname?: string, - backlog?: number, - callback?: (err?: ?Error) => mixed - ): ?Server; - listen( - port: number, - hostname?: string, - callback?: (err?: ?Error) => mixed - ): ?Server; - listen(port: number, callback?: (err?: ?Error) => mixed): ?Server; - listen(path: string, callback?: (err?: ?Error) => mixed): ?Server; - listen(handle: Object, callback?: (err?: ?Error) => mixed): ?Server; - disable(name: string): void; - disabled(name: string): boolean; - enable(name: string): express$Application; - enabled(name: string): boolean; - engine(name: string, callback: Function): void; - /** - * Mixed will not be taken as a value option. Issue around using the GET http method name and the get for settings. - */ - // get(name: string): mixed; - set(name: string, value: mixed): mixed; - render( - name: string, - optionsOrFunction: { [name: string]: mixed }, - callback: express$RenderCallback - ): void; - handle( - req: http$IncomingMessage, - res: http$ServerResponse, - next?: ?express$NextFunction - ): void; - // callable signature is not inherited - ( - req: http$IncomingMessage, - res: http$ServerResponse, - next?: ?express$NextFunction - ): void; -} - -declare type JsonOptions = { - inflate?: boolean, - limit?: string | number, - reviver?: (key: string, value: mixed) => mixed, - strict?: boolean, - type?: string | Array | ((req: express$Request) => boolean), - verify?: ( - req: express$Request, - res: express$Response, - buf: Buffer, - encoding: string - ) => mixed -}; - -declare type express$UrlEncodedOptions = { - extended?: boolean, - inflate?: boolean, - limit?: string | number, - parameterLimit?: number, - type?: string | Array | ((req: express$Request) => boolean), - verify?: ( - req: express$Request, - res: express$Response, - buf: Buffer, - encoding: string - ) => mixed, -} - -declare module "express" { - declare export type RouterOptions = express$RouterOptions; - declare export type CookieOptions = express$CookieOptions; - declare export type Middleware = express$Middleware; - declare export type NextFunction = express$NextFunction; - declare export type RequestParams = express$RequestParams; - declare export type $Response = express$Response; - declare export type $Request = express$Request; - declare export type $Application = express$Application; - declare export type LagoonErrorWithStatus = express$LagoonErrorWithStatus; - - declare module.exports: { - (): express$Application, // If you try to call like a function, it will use this signature - json: (opts: ?JsonOptions) => express$Middleware, - static: (root: string, options?: Object) => express$Middleware, // `static` property on the function - Router: typeof express$Router, // `Router` property on the function - urlencoded: (opts: ?express$UrlEncodedOptions) => express$Middleware, - }; -} diff --git a/flow-typed/custom/mocha.js b/flow-typed/custom/mocha.js deleted file mode 100644 index 8533f51cf..000000000 --- a/flow-typed/custom/mocha.js +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'mocha' { - declare module.exports: any; -} diff --git a/flow-typed/custom/ramda_v0.x.x.js b/flow-typed/custom/ramda_v0.x.x.js deleted file mode 100644 index ccd412c82..000000000 --- a/flow-typed/custom/ramda_v0.x.x.js +++ /dev/null @@ -1,2112 +0,0 @@ -type Transformer = { - "@@transducer/step": (r: A, a: *) => R, - "@@transducer/init": () => A, - "@@transducer/result": (result: *) => B -}; - -declare type $npm$ramda$Placeholder = { "@@functional/placeholder": true }; - -declare module ramda { - declare type UnaryFn = (a: A) => R; - declare type UnaryPromiseFn = UnaryFn>; - declare type BinaryFn = ((a: A, b: B) => R) & - ((a: A) => (b: B) => R); - declare type UnarySameTypeFn = UnaryFn; - declare type BinarySameTypeFn = BinaryFn; - declare type NestedObject = { [k: string]: T | NestedObject }; - declare type UnaryPredicateFn = (x: T) => boolean; - declare type MapUnaryPredicateFn = (V) => V => boolean; - declare type BinaryPredicateFn = (x: T, y: T) => boolean; - declare type BinaryPredicateFn2 = (x: T, y: S) => boolean; - - declare interface ObjPredicate { - (value: any, key: string): boolean; - } - - declare type __CurriedFunction1 = (...r: [AA]) => R; - declare type CurriedFunction1 = __CurriedFunction1; - - declare type __CurriedFunction2 = (( - ...r: [AA] - ) => CurriedFunction1) & - ((...r: [AA, BB]) => R); - declare type CurriedFunction2 = __CurriedFunction2; - - declare type __CurriedFunction3 = (( - ...r: [AA] - ) => CurriedFunction2) & - ((...r: [AA, BB]) => CurriedFunction1) & - ((...r: [AA, BB, CC]) => R); - declare type CurriedFunction3 = __CurriedFunction3< - A, - B, - C, - R, - *, - *, - * - >; - - declare type __CurriedFunction4< - A, - B, - C, - D, - R, - AA: A, - BB: B, - CC: C, - DD: D - > = ((...r: [AA]) => CurriedFunction3) & - ((...r: [AA, BB]) => CurriedFunction2) & - ((...r: [AA, BB, CC]) => CurriedFunction1) & - ((...r: [AA, BB, CC, DD]) => R); - declare type CurriedFunction4 = __CurriedFunction4< - A, - B, - C, - D, - R, - *, - *, - *, - * - >; - - declare type __CurriedFunction5< - A, - B, - C, - D, - E, - R, - AA: A, - BB: B, - CC: C, - DD: D, - EE: E - > = ((...r: [AA]) => CurriedFunction4) & - ((...r: [AA, BB]) => CurriedFunction3) & - ((...r: [AA, BB, CC]) => CurriedFunction2) & - ((...r: [AA, BB, CC, DD]) => CurriedFunction1) & - ((...r: [AA, BB, CC, DD, EE]) => R); - declare type CurriedFunction5 = __CurriedFunction5< - A, - B, - C, - D, - E, - R, - *, - *, - *, - *, - * - >; - - declare type __CurriedFunction6< - A, - B, - C, - D, - E, - F, - R, - AA: A, - BB: B, - CC: C, - DD: D, - EE: E, - FF: F - > = ((...r: [AA]) => CurriedFunction5) & - ((...r: [AA, BB]) => CurriedFunction4) & - ((...r: [AA, BB, CC]) => CurriedFunction3) & - ((...r: [AA, BB, CC, DD]) => CurriedFunction2) & - ((...r: [AA, BB, CC, DD, EE]) => CurriedFunction1) & - ((...r: [AA, BB, CC, DD, EE, FF]) => R); - declare type CurriedFunction6 = __CurriedFunction6< - A, - B, - C, - D, - E, - F, - R, - *, - *, - *, - *, - *, - * - >; - - declare type Curry = (((...r: [A]) => R) => CurriedFunction1) & - (((...r: [A, B]) => R) => CurriedFunction2) & - (((...r: [A, B, C]) => R) => CurriedFunction3) & - (( - (...r: [A, B, C, D]) => R - ) => CurriedFunction4) & - (( - (...r: [A, B, C, D, E]) => R - ) => CurriedFunction5) & - (( - (...r: [A, B, C, D, E, F]) => R - ) => CurriedFunction6); - - declare type Partial = (((...r: [A]) => R, args: [A]) => () => R) & - (((...r: [A, B]) => R, args: [A]) => B => R) & - (((...r: [A, B]) => R, args: [A, B]) => () => R) & - (((...r: [A, B, C]) => R, args: [A]) => (B, C) => R) & - (((...r: [A, B, C]) => R, args: [A, B]) => C => R) & - (((...r: [A, B, C]) => R, args: [A, B, C]) => () => R) & - (((...r: [A, B, C, D]) => R, args: [A]) => (B, C, D) => R) & - (((...r: [A, B, C, D]) => R, args: [A, B]) => (C, D) => R) & - (((...r: [A, B, C, D]) => R, args: [A, B, C]) => D => R) & - (( - (...r: [A, B, C, D]) => R, - args: [A, B, C, D] - ) => () => R) & - (( - (...r: [A, B, C, D, E]) => R, - args: [A] - ) => (B, C, D, E) => R) & - (( - (...r: [A, B, C, D, E]) => R, - args: [A, B] - ) => (C, D, E) => R) & - (( - (...r: [A, B, C, D, E]) => R, - args: [A, B, C] - ) => (D, E) => R) & - (( - (...r: [A, B, C, D, E]) => R, - args: [A, B, C, D] - ) => E => R) & - (( - (...r: [A, B, C, D, E]) => R, - args: [A, B, C, D, E] - ) => () => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A] - ) => (B, C, D, E, F) => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A, B] - ) => (C, D, E, F) => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A, B, C] - ) => (D, E, F) => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A, B, C, D] - ) => (E, F) => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A, B, C, D, E] - ) => F => R) & - (( - (...r: [A, B, C, D, E, F]) => R, - args: [A, B, C, D, E, F] - ) => () => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A] - ) => (B, C, D, E, F, G) => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B] - ) => (C, D, E, F, G) => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B, C] - ) => (D, E, F, G) => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B, C, D] - ) => (E, F, G) => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B, C, D, E] - ) => (F, G) => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B, C, D, E, F] - ) => G => R) & - (( - (...r: [A, B, C, D, E, F, G]) => R, - args: [A, B, C, D, E, F, G] - ) => () => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A] - ) => (B, C, D, E, F, G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B] - ) => (C, D, E, F, G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C] - ) => (D, E, F, G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C, D] - ) => (E, F, G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C, D, E] - ) => (F, G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C, D, E, F] - ) => (G, H) => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C, D, E, F, G] - ) => H => R) & - (( - (...r: [A, B, C, D, E, F, G, H]) => R, - args: [A, B, C, D, E, F, G, H] - ) => () => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A] - ) => (B, C, D, E, F, G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B] - ) => (C, D, E, F, G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C] - ) => (D, E, F, G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D] - ) => (E, F, G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D, E] - ) => (F, G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D, E, F] - ) => (G, H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D, E, F, G] - ) => (H, I) => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D, E, F, G, H] - ) => I => R) & - (( - (...r: [A, B, C, D, E, F, G, H, I]) => R, - args: [A, B, C, D, E, F, G, H, I] - ) => () => R); - - declare type Pipe = (( - ab: UnaryFn, - bc: UnaryFn, - cd: UnaryFn, - de: UnaryFn, - ef: UnaryFn, - fg: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - ab: UnaryFn, - bc: UnaryFn, - cd: UnaryFn, - de: UnaryFn, - ef: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - ab: UnaryFn, - bc: UnaryFn, - cd: UnaryFn, - de: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - ab: UnaryFn, - bc: UnaryFn, - cd: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - ab: UnaryFn, - bc: UnaryFn, - ...rest: Array - ) => UnaryFn) & - ((ab: UnaryFn, ...rest: Array) => UnaryFn); - - declare type PipeP = (( - ab: UnaryPromiseFn, - bc: UnaryPromiseFn, - cd: UnaryPromiseFn, - de: UnaryPromiseFn, - ef: UnaryPromiseFn, - fg: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn) & - (( - ab: UnaryPromiseFn, - bc: UnaryPromiseFn, - cd: UnaryPromiseFn, - de: UnaryPromiseFn, - ef: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn) & - (( - ab: UnaryPromiseFn, - bc: UnaryPromiseFn, - cd: UnaryPromiseFn, - de: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn) & - (( - ab: UnaryPromiseFn, - bc: UnaryPromiseFn, - cd: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn) & - (( - ab: UnaryPromiseFn, - bc: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn) & - (( - ab: UnaryPromiseFn, - ...rest: Array - ) => UnaryPromiseFn); - - declare type Compose = (( - fg: UnaryFn, - ef: UnaryFn, - de: UnaryFn, - cd: UnaryFn, - bc: UnaryFn, - ab: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - ef: UnaryFn, - de: UnaryFn, - cd: UnaryFn, - bc: UnaryFn, - ab: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - de: UnaryFn, - cd: UnaryFn, - bc: UnaryFn, - ab: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - cd: UnaryFn, - bc: UnaryFn, - ab: UnaryFn, - ...rest: Array - ) => UnaryFn) & - (( - bc: UnaryFn, - ab: UnaryFn, - ...rest: Array - ) => UnaryFn) & - ((ab: UnaryFn, ...rest: Array) => UnaryFn); - - declare type Filter = ( | { +[key: K]: V }>( - fn: UnaryPredicateFn, - xs: T - ) => T) & - ( | { +[key: K]: V }>( - fn: UnaryPredicateFn - ) => (xs: T) => T); - - declare class Monad { - chain: Function; - } - - declare class Semigroup {} - - declare class Chain { - chain | Array>(fn: (a: T) => V, x: V): V; - chain | Array>(fn: (a: T) => V): (x: V) => V; - } - - declare class GenericContructor { - constructor(x: T): GenericContructor; - } - - declare class GenericContructorMulti { - constructor(...args: Array): GenericContructor; - } - - /** - * DONE: - * Function* - * List* - * Logic - * Math - * Object* - * Relation - * String - * Type - */ - - declare var compose: Compose; - declare var composeP: Function; - declare var pipe: Pipe; - // declare var pipeP: PipeP; - declare var pipeP: Function; - declare var curry: Curry; - declare function curryN( - length: number, - fn: (...args: Array) => any - ): Function; - - // *Math - declare var add: CurriedFunction2; - declare var inc: UnaryFn; - declare var dec: UnaryFn; - declare var mean: UnaryFn, number>; - declare var divide: CurriedFunction2; - declare var mathMod: CurriedFunction2; - declare var median: UnaryFn, number>; - declare var modulo: CurriedFunction2; - declare var multiply: CurriedFunction2; - declare var negate: UnaryFn; - declare var product: UnaryFn, number>; - declare var subtract: CurriedFunction2; - declare var sum: UnaryFn, number>; - - // Filter - declare var filter: Filter; - declare var reject: Filter; - - // *String - declare var match: CurriedFunction2>; - declare var replace: CurriedFunction3< - RegExp | string, - string | ((substring: string, ...args: Array) => string), - string, - string - >; - declare var split: CurriedFunction2>; - declare var test: CurriedFunction2; - // startsWith and endsWith use the same signature: - declare type EdgeWith = - & ( - & ((Array) => (Array) => boolean) - & (Array, Array) => boolean - ) - & ( - & ((string) => (string) => boolean) - & (string, string) => boolean - ) - ; - declare var startsWith: EdgeWith<*>; - declare var endsWith: EdgeWith<*>; - declare function toLower(a: string): string; - declare function toString(x: any): string; - declare function toUpper(a: string): string; - declare function trim(a: string): string; - - // *Type - declare function is(t: T, ...rest: Array): (v: any) => boolean; - declare function is(t: T, v: any): boolean; - declare var propIs: CurriedFunction3; - declare function type(x: ?any): string; - declare function isArrayLike(x: any): boolean; - - declare function isNil(x: mixed): boolean %checks(x === undefined || - x === null); - - // *List - declare function adjust( - fn: (a: T) => T, - ...rest: Array - ): (index: number, ...rest: Array) => (src: Array) => Array; - declare function adjust( - fn: (a: T) => T, - index: number, - ...rest: Array - ): (src: Array) => Array; - declare function adjust( - fn: (a: T) => T, - index: number, - src: Array - ): Array; - - declare function all(fn: UnaryPredicateFn, xs: Array): boolean; - declare function all( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: Array) => boolean; - - declare function any(fn: UnaryPredicateFn, xs: Array): boolean; - declare function any( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: Array) => boolean; - - declare function aperture(n: number, xs: Array): Array>; - declare function aperture( - n: number, - ...rest: Array - ): (xs: Array) => Array>; - - declare function append(x: E, xs: Array): Array; - declare function append( - x: E, - ...rest: Array - ): (xs: Array) => Array; - - declare function prepend(x: E, xs: Array): Array; - declare function prepend( - x: E, - ...rest: Array - ): (xs: Array) => Array; - - declare function concat | string>(x: T, y: T): T; - declare function concat | string>(x: T): (y: T) => T; - - declare function contains | string>(x: E, xs: T): boolean; - declare function contains | string>( - x: E, - // Not sure why this doesn't work: - // ...rest: Array - ...rest: Array - ): (xs: T) => boolean; - - declare function drop | string>( - n: number, - ...rest: Array - ): (xs: T) => T; - declare function drop | string>(n: number, xs: T): T; - - declare function dropLast | string>( - n: number, - ...rest: Array - ): (xs: T) => T; - declare function dropLast | string>(n: number, xs: T): T; - - declare function dropLastWhile>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T) => T; - declare function dropLastWhile>( - fn: UnaryPredicateFn, - xs: T - ): T; - - declare function dropWhile>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T) => T; - declare function dropWhile>(fn: UnaryPredicateFn, xs: T): T; - - declare function dropRepeats>(xs: T): T; - - declare function dropRepeatsWith>( - fn: BinaryPredicateFn, - ...rest: Array - ): (xs: T) => T; - declare function dropRepeatsWith>( - fn: BinaryPredicateFn, - xs: T - ): T; - - declare function groupBy( - fn: (x: T) => string, - xs: Array - ): { [key: string]: Array }; - declare function groupBy( - fn: (x: T) => string, - ...rest: Array - ): (xs: Array) => { [key: string]: Array }; - - declare function groupWith | string>( - fn: BinaryPredicateFn, - xs: V - ): Array; - declare function groupWith | string>( - fn: BinaryPredicateFn, - ...rest: Array - ): (xs: V) => Array; - - // declare function head>(xs: V): ?T; - // declare function head(xs: V): V; - declare function head(...args: Array): any; - - declare function into, R: Array<*> | string | Object>( - accum: R, - xf: (a: A) => I, - input: A - ): R; - declare function into, R>( - accum: Transformer, - xf: (a: A) => R, - input: A - ): R; - - declare function indexOf(x: ?E, xs: Array): number; - declare function indexOf( - x: ?E, - ...rest: Array - ): (xs: Array) => number; - - declare function indexBy( - fn: (x: T) => string, - ...rest: Array - ): (xs: Array) => { [key: string]: T }; - declare function indexBy( - fn: (x: T) => string, - xs: Array - ): { [key: string]: T }; - - declare function insert( - index: number, - ...rest: Array - ): (elem: T) => (src: Array) => Array; - declare function insert( - index: number, - elem: T, - ...rest: Array - ): (src: Array) => Array; - declare function insert(index: number, elem: T, src: Array): Array; - - declare function insertAll( - index: number, - ...rest: Array - ): (elem: Array) => (src: Array) => Array; - declare function insertAll( - index: number, - elems: Array, - ...rest: Array - ): (src: Array) => Array; - declare function insertAll( - index: number, - elems: Array, - src: Array - ): Array; - - declare function join(x: string, xs: Array): string; - declare function join( - x: string, - ...rest: Array - ): (xs: Array) => string; - - declare function last>(xs: V): ?T; - declare function last(xs: V): V; - - declare function none(fn: UnaryPredicateFn, xs: Array): boolean; - declare function none( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: Array) => boolean; - - declare function nth>(i: number, xs: T): ?V; - declare function nth | string>( - i: number, - ...rest: Array - ): ((xs: string) => string) & ((xs: T) => ?V); - declare function nth(i: number, xs: T): T; - - declare type Find = (>( - fn: UnaryPredicateFn - ) => (xs: T) => ?V) & - (>(fn: UnaryPredicateFn, xs: T) => ?V); - - declare var find: Find; - - declare function findLast | O>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T | O) => ?V | O; - declare function findLast | O>( - fn: UnaryPredicateFn, - xs: T | O - ): ?V | O; - - declare function findIndex | { [key: K]: V }>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T) => number; - declare function findIndex | { [key: K]: V }>( - fn: UnaryPredicateFn, - xs: T - ): number; - declare function findLastIndex | { [key: K]: V }>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T) => number; - declare function findLastIndex | { [key: K]: V }>( - fn: UnaryPredicateFn, - xs: T - ): number; - - declare function forEach(fn: (x: T) => ?V, xs: Array): Array; - declare function forEach( - fn: (x: T) => ?V, - ...rest: Array - ): (xs: Array) => Array; - - declare function forEachObjIndexed( - fn: (val: A, key: string, o: O) => B, - o: { [key: string]: A } - ): O; - - declare function forEachObjIndexed( - fn: (val: A, key: string, o: O) => B, - ...args: Array - ): (o: { [key: string]: A }) => O; - - declare function lastIndexOf(x: E, xs: Array): number; - declare function lastIndexOf( - x: E, - ...rest: Array - ): (xs: Array) => number; - - declare function map(fn: (x: T) => R, xs: Array): Array; - declare function map(fn: (x: T) => R, xs: S): S; - declare function map( - fn: (x: T) => R, - ...rest: Array - ): ((xs: { [key: string]: T }) => { [key: string]: R }) & - ((xs: Array) => Array); - declare function map( - fn: (x: T) => R, - ...rest: Array - ): ((xs: S) => S) & ((xs: S) => S); - declare function map( - fn: (x: T) => R, - xs: { [key: string]: T } - ): { [key: string]: R }; - - declare type AccumIterator = (acc: R, x: A) => [R, B]; - declare function mapAccum( - fn: AccumIterator, - acc: R, - xs: Array - ): [R, Array]; - declare function mapAccum( - fn: AccumIterator, - ...rest: Array - ): (acc: R, xs: Array) => [R, Array]; - - declare function mapAccumRight( - fn: AccumIterator, - acc: R, - xs: Array - ): [R, Array]; - declare function mapAccumRight( - fn: AccumIterator, - ...rest: Array - ): (acc: R, xs: Array) => [R, Array]; - - declare function intersperse(x: E, xs: Array): Array; - declare function intersperse( - x: E, - ...rest: Array - ): (xs: Array) => Array; - - declare function pair(a: A, b: B): [A, B]; - declare function pair(a: A, ...rest: Array): (b: B) => [A, B]; - - declare function partition | { [key: K]: V }>( - fn: UnaryPredicateFn, - xs: T - ): [T, T]; - declare function partition | { [key: K]: V }>( - fn: UnaryPredicateFn, - ...rest: Array - ): (xs: T) => [T, T]; - - declare function pluck< - V, - K: string | number, - T: Array | { [key: string]: V }> - >( - k: K, - xs: T - ): Array; - declare function pluck< - V, - K: string | number, - T: Array | { [key: string]: V }> - >( - k: K, - ...rest: Array - ): (xs: T) => Array; - - declare var range: CurriedFunction2>; - - declare function remove( - from: number, - ...rest: Array - ): ((to: number, ...rest: Array) => (src: Array) => Array) & - ((to: number, src: Array) => Array); - declare function remove( - from: number, - to: number, - ...rest: Array - ): (src: Array) => Array; - declare function remove(from: number, to: number, src: Array): Array; - - declare function repeat(x: T, times: number): Array; - declare function repeat( - x: T, - ...rest: Array - ): (times: number) => Array; - - declare function slice | string>( - from: number, - ...rest: Array - ): ((to: number, ...rest: Array) => (src: T) => T) & - ((to: number, src: T) => T); - declare function slice | string>( - from: number, - to: number, - ...rest: Array - ): (src: T) => T; - declare function slice | string>( - from: number, - to: number, - src: T - ): T; - - declare function sort>(fn: (a: V, b: V) => number, xs: T): T; - declare function sort>( - fn: (a: V, b: V) => number, - ...rest: Array - ): (xs: T) => T; - - declare function sortWith>( - fns: Array<(a: V, b: V) => number>, - xs: T - ): T; - declare function sortWith>( - fns: Array<(a: V, b: V) => number>, - ...rest: Array - ): (xs: T) => T; - - declare function descend(A => B): (A => A) => number - declare function ascend(A => B): (A => A) => number - - declare function times(fn: (i: number) => T, n: number): Array; - declare function times( - fn: (i: number) => T, - ...rest: Array - ): (n: number) => Array; - - declare function take | string>(n: number, xs: T): T; - declare function take | string>(n: number): (xs: T) => T; - - declare function takeLast | string>(n: number, xs: T): T; - declare function takeLast | string>(n: number): (xs: T) => T; - - declare function takeLastWhile>( - fn: UnaryPredicateFn, - xs: T - ): T; - declare function takeLastWhile>( - fn: UnaryPredicateFn - ): (xs: T) => T; - - declare function takeWhile>(fn: UnaryPredicateFn, xs: T): T; - declare function takeWhile>( - fn: UnaryPredicateFn - ): (xs: T) => T; - - declare function unfold( - fn: (seed: T) => [R, T] | boolean, - ...rest: Array - ): (seed: T) => Array; - declare function unfold( - fn: (seed: T) => [R, T] | boolean, - seed: T - ): Array; - - declare function uniqBy( - fn: (x: T) => V, - ...rest: Array - ): (xs: Array) => Array; - declare function uniqBy(fn: (x: T) => V, xs: Array): Array; - - declare function uniqWith( - fn: BinaryPredicateFn, - ...rest: Array - ): (xs: Array) => Array; - declare function uniqWith( - fn: BinaryPredicateFn, - xs: Array - ): Array; - - declare function update( - index: number, - ...rest: Array - ): ((elem: T, ...rest: Array) => (src: Array) => Array) & - ((elem: T, src: Array) => Array); - declare function update( - index: number, - elem: T, - ...rest: Array - ): (src: Array) => Array; - declare function update(index: number, elem: T, src: Array): Array; - - // TODO `without` as a transducer - declare function without(xs: Array, src: Array): Array; - declare function without( - xs: Array, - ...rest: Array - ): (src: Array) => Array; - - declare function xprod(xs: Array, ys: Array): Array<[T, S]>; - declare function xprod( - xs: Array, - ...rest: Array - ): (ys: Array) => Array<[T, S]>; - - declare function zip(xs: Array, ys: Array): Array<[T, S]>; - declare function zip( - xs: Array, - ...rest: Array - ): (ys: Array) => Array<[T, S]>; - - declare function zipObj( - xs: Array, - ys: Array - ): { [key: T]: S }; - declare function zipObj( - xs: Array, - ...rest: Array - ): (ys: Array) => { [key: T]: S }; - - declare type NestedArray = Array>; - declare function flatten(xs: NestedArray): Array; - - declare function fromPairs(pair: Array<[T, V]>): { [key: string]: V }; - - declare function init | string>(xs: V): V; - - // declare function length(xs: ?Array): number; - declare function length(...args: Array): any; - - - declare function reverse | string>(xs: V): V; - - // $FlowFixMe - declare type Reduce = (( - fn: (acc: A, elm: B) => A - ) => ((init: A) => (xs: Array | $ReadOnlyArray) => A) & - ((init: A, xs: Array | $ReadOnlyArray) => A)) & - (( - fn: (acc: A, elm: B) => A, - init: A - ) => (xs: Array | $ReadOnlyArray) => A) & - (( - // $FlowFixMe - fn: (acc: A, elm: B) => A, - init: A, - xs: Array | $ReadOnlyArray - ) => A); - - declare var reduce: Reduce; - - declare function reduceBy( - fn: (acc: B, elem: A) => B, - ...rest: Array - ): (( - acc: B, - ...rest: Array - ) => (( - keyFn: (elem: A) => string, - ...rest: Array - ) => (xs: Array) => { [key: string]: B }) & - ((keyFn: (elem: A) => string, xs: Array) => { [key: string]: B })) & - (( - acc: B, - keyFn: (elem: A) => string, - ...rest: Array - ) => (xs: Array) => { [key: string]: B }) & - (( - acc: B, - keyFn: (elem: A) => string, - xs: Array - ) => { [key: string]: B }); - declare function reduceBy( - fn: (acc: B, elem: A) => B, - acc: B, - ...rest: Array - ): (( - keyFn: (elem: A) => string, - ...rest: Array - ) => (xs: Array) => { [key: string]: B }) & - ((keyFn: (elem: A) => string, xs: Array) => { [key: string]: B }); - declare function reduceBy( - fn: (acc: B, elem: A) => B, - acc: B, - keyFn: (elem: A) => string - ): (xs: Array) => { [key: string]: B }; - declare function reduceBy( - fn: (acc: B, elem: A) => B, - acc: B, - keyFn: (elem: A) => string, - xs: Array - ): { [key: string]: B }; - - declare function reduceRight( - fn: (elem: B, acc: A) => A, - ...rest: Array - ): ((init: A, xs: Array) => A) & - ((init: A, ...rest: Array) => (xs: Array) => A); - declare function reduceRight( - fn: (elem: B, acc: A) => A, - init: A, - ...rest: Array - ): (xs: Array) => A; - declare function reduceRight( - fn: (elem: B, acc: A) => A, - init: A, - xs: Array - ): A; - - declare function reduceWhile( - pred: (acc: A, curr: B) => boolean, - ...rest: Array - ): (( - fn: (a: A, b: B) => A, - ...rest: Array - ) => ( - init: A, - ...rest: Array - ) => ( - xs: Array - ) => A & - (( - fn: (a: A, b: B) => A, - ...rest: Array - ) => (init: A, xs: Array) => A)) & - (( - fn: (a: A, b: B) => A, - init: A, - ...rest: Array - ) => (xs: Array) => A) & - ((fn: (a: A, b: B) => A, init: A, xs: Array) => A); - - declare function reduceWhile( - pred: (acc: A, curr: B) => boolean, - fn: (a: A, b: B) => A, - ...rest: Array - ): ((init: A, ...rest: Array) => (xs: Array) => A) & - ((init: A, xs: Array) => A); - - declare function reduceWhile( - fn: (acc: A, curr: B) => boolean, - fn: (a: A, b: B) => A, - init: A, - xs: Array - ): A; - - declare function scan( - fn: (acc: A, elem: B) => A, - ...rest: Array - ): ((init: A, xs: Array) => Array) & - ((init: A, ...rest: Array) => (xs: Array) => Array); - declare function scan( - fn: (acc: A, elem: B) => A, - init: A, - ...rest: Array - ): (xs: Array) => Array; - declare function scan( - fn: (acc: A, elem: B) => A, - init: A, - xs: Array - ): Array; - - declare function splitAt | string>(i: number, xs: T): [T, T]; - declare function splitAt | string>( - i: number - ): (xs: T) => [T, T]; - declare function splitEvery | string>( - i: number, - xs: T - ): Array; - declare function splitEvery | string>( - i: number - ): (xs: T) => Array; - declare function splitWhen>( - fn: UnaryPredicateFn, - xs: T - ): [T, T]; - declare function splitWhen>( - fn: UnaryPredicateFn - ): (xs: T) => [T, T]; - - declare function tail | string>(xs: V): V; - - declare function transpose(xs: Array>): Array>; - - // declare function uniq(xs: Array): Array; - declare function uniq(...args: Array): any; - - declare function unnest(xs: NestedArray): NestedArray; - - declare function zipWith( - fn: (a: T, b: S) => R, - ...rest: Array - ): ((xs: Array, ys: Array) => Array) & - ((xs: Array, ...rest: Array) => (ys: Array) => Array); - declare function zipWith( - fn: (a: T, b: S) => R, - xs: Array, - ...rest: Array - ): (ys: Array) => Array; - declare function zipWith( - fn: (a: T, b: S) => R, - xs: Array, - ys: Array - ): Array; - - // *Relation - declare function equals(x: T, ...rest: Array): (y: T) => boolean; - declare function equals(x: T, y: T): boolean; - - declare function eqBy( - fn: (x: A) => B, - ...rest: Array - ): ((x: A, y: A) => boolean) & - ((x: A, ...rest: Array) => (y: A) => boolean); - declare function eqBy( - fn: (x: A) => B, - x: A, - ...rest: Array - ): (y: A) => boolean; - declare function eqBy(fn: (x: A) => B, x: A, y: A): boolean; - - // Flow cares about the order in which these appear. Generally function - // siguatures should go from smallest arity to largest arity. - declare type PropEq = (( - prop: $Keys - ) => ((val: mixed) => (obj: T) => boolean) & - ((val: mixed, obj: T) => boolean)) & - ((prop: $Keys, val: mixed) => (obj: T) => boolean) & - ((prop: $Keys, val: mixed, obj: T) => boolean) & - // Array variants. - (( - prop: number - ) => ((val: mixed) => (obj: Array<*>) => boolean) & - ((val: mixed, obj: Array<*>) => boolean)) & - ((prop: number, val: mixed) => (obj: Array<*>) => boolean) & - ((prop: number, val: mixed, obj: Array<*>) => boolean); - declare var propEq: PropEq; - - declare function pathEq( - path: Array, - ...rest: Array - ): ((val: any, o: Object) => boolean) & - ((val: any, ...rest: Array) => (o: Object) => boolean); - declare function pathEq( - path: Array, - val: any, - ...rest: Array - ): (o: Object) => boolean; - declare function pathEq(path: Array, val: any, o: Object): boolean; - - declare function clamp( - min: T, - ...rest: Array - ): ((max: T, ...rest: Array) => (v: T) => T) & ((max: T, v: T) => T); - declare function clamp( - min: T, - max: T, - ...rest: Array - ): (v: T) => T; - declare function clamp(min: T, max: T, v: T): T; - - declare function countBy( - fn: (x: T) => string, - ...rest: Array - ): (list: Array) => { [key: string]: number }; - declare function countBy( - fn: (x: T) => string, - list: Array - ): { [key: string]: number }; - - declare function difference( - xs1: Array, - ...rest: Array - ): (xs2: Array) => Array; - declare function difference(xs1: Array, xs2: Array): Array; - - declare function differenceWith( - fn: BinaryPredicateFn, - ...rest: Array - ): ((xs1: Array) => (xs2: Array) => Array) & - ((xs1: Array, xs2: Array) => Array); - declare function differenceWith( - fn: BinaryPredicateFn, - xs1: Array, - ...rest: Array - ): (xs2: Array) => Array; - declare function differenceWith( - fn: BinaryPredicateFn, - xs1: Array, - xs2: Array - ): Array; - - declare function eqBy(fn: (x: T) => T, x: T, y: T): boolean; - declare function eqBy(fn: (x: T) => T): (x: T, y: T) => boolean; - declare function eqBy(fn: (x: T) => T, x: T): (y: T) => boolean; - declare function eqBy(fn: (x: T) => T): (x: T) => (y: T) => boolean; - - declare function gt(x: T, ...rest: Array): (y: T) => boolean; - declare function gt(x: T, y: T): boolean; - - declare function gte(x: T, ...rest: Array): (y: T) => boolean; - declare function gte(x: T, y: T): boolean; - - declare function identical(x: T, ...rest: Array): (y: T) => boolean; - declare function identical(x: T, y: T): boolean; - - declare function innerJoin( - pred: (a: A, b: B) => boolean, - ...rest: Array - ): ( - a: Array, - ...rest: Array - ) => (b: Array) => Array & ((a: Array, b: Array) => Array); - declare function innerJoin( - pred: (a: A, b: B) => boolean, - a: Array, - ...rest: Array - ): (b: Array) => Array; - declare function innerJoin( - pred: (a: A, b: B) => boolean, - a: Array, - b: Array - ): Array; - - declare function intersection(x: Array, y: Array): Array; - declare function intersection(x: Array): (y: Array) => Array; - - declare function intersectionWith( - fn: BinaryPredicateFn, - ...rest: Array - ): ((x: Array, y: Array) => Array) & - ((x: Array) => (y: Array) => Array); - declare function intersectionWith( - fn: BinaryPredicateFn, - x: Array, - ...rest: Array - ): (y: Array) => Array; - declare function intersectionWith( - fn: BinaryPredicateFn, - x: Array, - y: Array - ): Array; - - declare function lt(x: T, ...rest: Array): (y: T) => boolean; - declare function lt(x: T, y: T): boolean; - - declare function lte(x: T, ...rest: Array): (y: T) => boolean; - declare function lte(x: T, y: T): boolean; - - declare function max(x: T, ...rest: Array): (y: T) => T; - declare function max(x: T, y: T): T; - - declare function maxBy( - fn: (x: T) => V, - ...rest: Array - ): ((x: T, y: T) => T) & ((x: T) => (y: T) => T); - declare function maxBy( - fn: (x: T) => V, - x: T, - ...rest: Array - ): (y: T) => T; - declare function maxBy(fn: (x: T) => V, x: T, y: T): T; - - declare function min(x: T, ...rest: Array): (y: T) => T; - declare function min(x: T, y: T): T; - - declare function minBy( - fn: (x: T) => V, - ...rest: Array - ): ((x: T, y: T) => T) & ((x: T) => (y: T) => T); - declare function minBy( - fn: (x: T) => V, - x: T, - ...rest: Array - ): (y: T) => T; - declare function minBy(fn: (x: T) => V, x: T, y: T): T; - - declare function sortBy( - fn: (x: T) => V, - ...rest: Array - ): (x: Array) => Array; - declare function sortBy(fn: (x: T) => V, x: Array): Array; - - declare function symmetricDifference( - x: Array, - ...rest: Array - ): (y: Array) => Array; - declare function symmetricDifference(x: Array, y: Array): Array; - - declare function symmetricDifferenceWith( - fn: BinaryPredicateFn, - ...rest: Array - ): ((x: Array, ...rest: Array) => (y: Array) => Array) & - ((x: Array, y: Array) => Array); - declare function symmetricDifferenceWith( - fn: BinaryPredicateFn, - x: Array, - ...rest: Array - ): (y: Array) => Array; - declare function symmetricDifferenceWith( - fn: BinaryPredicateFn, - x: Array, - y: Array - ): Array; - - // declare function union( - // x: Array, - // ...rest: Array - // ): (y: Array) => Array; - // declare function union(x: Array, y: Array): Array; - declare function union(...args: Array): any; - - declare function unionWith( - fn: BinaryPredicateFn, - ...rest: Array - ): ((x: Array, ...rest: Array) => (y: Array) => Array) & - ((x: Array, y: Array) => Array); - declare function unionWith( - fn: BinaryPredicateFn, - x: Array, - ...rest: Array - ): (y: Array) => Array; - declare function unionWith( - fn: BinaryPredicateFn, - x: Array, - y: Array - ): Array; - - // *Object - declare function assoc( - key: string, - ...args: Array - ): ((val: T, ...rest: Array) => (src: S) => { [k: string]: T }) & - ((val: T, src: S) => { [k: string]: T } & S); - declare function assoc( - key: string, - val: T, - ...args: Array - ): (src: S) => { [k: string]: T } & S; - declare function assoc( - key: string, - val: T, - src: S - ): { [k: string]: T } & S; - - declare function assocPath( - key: Array, - ...args: Array - ): ((val: T, ...rest: Array) => (src: S) => { [k: string]: T }) & - ((val: T) => (src: S) => { [k: string]: T } & S); - declare function assocPath( - key: Array, - val: T, - ...args: Array - ): (src: S) => { [k: string]: T } & S; - declare function assocPath( - key: Array, - val: T, - src: S - ): { [k: string]: T } & S; - - declare function clone(src: T): $Shape; - - declare function dissoc( - key: string, - ...args: Array - ): (src: { [k: string]: T }) => { [k: string]: T }; - declare function dissoc( - key: string, - src: { [k: string]: T } - ): { [k: string]: T }; - - declare function dissocPath( - key: Array, - ...args: Array - ): (src: { [k: string]: T }) => { [k: string]: T }; - declare function dissocPath( - key: Array, - src: { [k: string]: T } - ): { [k: string]: T }; - - declare function evolve(NestedObject, A): A; - declare function evolve(NestedObject): A => A; - - declare function eqProps( - key: string, - ...args: Array - ): ((o1: Object, ...rest: Array) => (o2: Object) => boolean) & - ((o1: Object, o2: Object) => boolean); - declare function eqProps( - key: string, - o1: Object, - ...args: Array - ): (o2: Object) => boolean; - declare function eqProps(key: string, o1: Object, o2: Object): boolean; - - declare function has(key: string, o: Object): boolean; - declare function has(key: string): (o: Object) => boolean; - - declare function hasIn(key: string, o: Object): boolean; - declare function hasIn(key: string): (o: Object) => boolean; - - declare function invert(o: Object): { [k: string]: Array }; - declare function invertObj(o: Object): { [k: string]: string }; - - declare function keys(o: Object): Array; - - declare type Lens = (x: T) => V; - - declare function lens( - getter: (s: T) => U, - setter: (a: U, s: T) => V - ): Lens; - declare function lens( - getter: (s: T) => U - ): (setter: (a: U, s: T) => V) => Lens; - - declare function lensIndex(n: number): Lens; - - declare function lensPath(a: Array): Lens; - - declare function lensProp(str: string): Lens; - - declare function mapObjIndexed( - fn: (val: A, key: string, o: Object) => B, - o: { [key: string]: A } - ): { [key: string]: B }; - declare function mapObjIndexed( - fn: (val: A, key: string, o: Object) => B, - ...args: Array - ): (o: { [key: string]: A }) => { [key: string]: B }; - - declare type Merge = ((a: A, b: B) => A & B) & - ((a: A, ...rest: Array) => (b: B) => A & B); - - declare var merge: Merge; - - declare function mergeAll( - os: Array<{ [k: string]: T }> - ): { [k: string]: T }; - - declare var mergeDeepLeft: Merge; - - declare var mergeDeepRight: ((a: A, b: B) => B & A) & - ((a: A, ...rest: Array) => (b: B) => B & A); - - declare type MergeWith = (( - fn: (a: T, b: T) => T, - a: A, - b: B - ) => A & B) & - (( - fn: (a: T, b: T) => T, - ...rest: Array - ) => (a: A, ...rest: Array) => (b: B) => A & B) & - (( - fn: (a: T, b: T) => T, - ...rest: Array - ) => (a: A, b: B) => A & B) & - (( - fn: (a: T, b: T) => T, - a: A, - ...rest: Array - ) => (b: B) => A & B); - - declare type MergeWithKey = (< - S: string, - A: { [k: string]: T }, - B: { [k: string]: T }, - T - >( - fn: (s: S, a: T, b: T) => T, - a: A, - b: B - ) => A & B) & - (( - fn: (s: S, a: T, b: T) => T, - ...rest: Array - ) => (a: A, b: B) => A & B) & - (( - fn: (s: S, a: T, b: T) => T, - ...rest: Array - ) => (a: A, ...rest: Array) => (b: B) => A & B) & - (( - fn: (s: S, a: T, b: T) => T, - a: A, - ...rest: Array - ) => (b: B) => A & B); - - declare var mergeDeepWith: MergeWith; - - declare var mergeDeepWithKey: MergeWithKey; - - declare var mergeWith: MergeWith; - - declare var mergeWithKey: MergeWithKey; - - declare function objOf( - key: string, - ...rest: Array - ): (val: T) => { [key: string]: T }; - declare function objOf(key: string, val: T): { [key: string]: T }; - - declare function omit( - keys: Array, - ...rest: Array - ): (val: T) => Object; - declare function omit(keys: Array, val: T): Object; - - declare function over(lens: Lens, x: (any) => mixed, val: V): U; - declare function over( - lens: Lens, - ...rest: Array - ): ((x: (any) => mixed, ...rest: Array) => (val: V) => U) & ((x: (any) => mixed, val: V) => U); - - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: NestedObject) => V; - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: null | void) => void; - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: mixed) => ?V; - // declare function path>(p: Array, o: A): V; - // declare function path(p: Array, o: A): void; - // declare function path(p: Array, o: A): ?V; - - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: NestedObject) => V; - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: null | void) => void; - // declare function path( - // p: Array, - // ...rest: Array - // ): (o: mixed) => ?V; - // declare function path>(p: Array, o: A): V; - // declare function path(p: Array, o: A): void; - // declare function path(p: Array, o: A): ?V; - declare function path(...args: Array): any; - - // declare function pathOr>( - // or: T, - // ...rest: Array - // ): ((p: Array, ...rest: Array) => (o: ?A) => V | T) & - // ((p: Array, o: ?A) => V | T); - // declare function pathOr>( - // or: T, - // p: Array, - // ...rest: Array - // ): (o: ?A) => V | T; - // declare function pathOr>( - // or: T, - // p: Array, - // o: ?A - // ): V | T; - declare function pathOr(...args: Array): any; - - declare function pick( - keys: Array, - ...rest: Array - ): (val: O) => { ...$Exact }; - declare function pick( - keys: Array, - val: O - ): { ...$Exact }; - - declare function pickAll( - keys: Array, - ...rest: Array - ): (val: { [key: string]: A }) => { [key: string]: ?A }; - declare function pickAll( - keys: Array, - val: { [key: string]: A } - ): { [key: string]: ?A }; - - declare function pickBy( - fn: Function, - ...rest: Array - ): (val: O) => { ...$Exact }; - declare function pickBy( - fn: Function, - val: O - ): { ...$Exact }; - - declare function project( - keys: Array, - ...rest: Array - ): (val: Array<{ [key: string]: T }>) => Array<{ [key: string]: T }>; - declare function project( - keys: Array, - val: Array<{ [key: string]: T }> - ): Array<{ [key: string]: T }>; - - declare function prop(key: T, o: O): $ElementType; - declare function prop( - key: T, - ...rest: Array - ): (o: O) => $ElementType; - declare function prop( - __: $npm$ramda$Placeholder, - o: O - ): (key: T) => $ElementType; - - declare function prop(key: T, o: null | void): void; - declare function prop( - key: T, - ...rest: Array - ): (o: null | void) => void; - declare function prop( - __: $npm$ramda$Placeholder, - o: null | void - ): (key: T) => void; - - declare function propOr(or: T, p: string, o: O): $ElementType | T; - declare function propOr( - or: T, - p: string, - ...rest: Array - ): (o: O) => $ElementType | T; - declare function propOr( - or: T, - ...rest: Array - ): ((p: string, ...rest: Array) => (o: O) => $ElementType | T) & - ((p: string, o: O) => $ElementType | T) - - declare function propOr(or: T, p: string, o: null | void): T; - declare function propOr( - or: T, - p: string, - ...rest: Array - ): (o: null | void) => T; - declare function propOr( - or: T, - ...rest: Array - ): ((p: string, ...rest: Array) => (o: null | void) => T) & - ((p: string, o: null | void) => T) - - declare function keysIn(o: Object): Array; - - declare function props( - keys: Array, - ...rest: Array - ): (o: O) => Array<$ElementType>; - declare function props( - keys: Array, - o: O - ): Array<$ElementType>; - - declare function set(lens: Lens, x: T, val: V): U; - declare function set( - lens: Lens, - ...rest: Array - ): ((x: (any) => mixed, ...rest: Array) => (val: V) => U) & ((x: (any) => mixed, val: V) => U); - - declare function toPairs( - o: O - ): Array<[$Keys, T]>; - - declare function toPairsIn( - o: O - ): Array<[string, T]>; - - declare function values(o: T): Array<$Values>; - - declare function valuesIn(o: O): Array; - - declare function where( - predObj: $ObjMap, - o: O - ): boolean; - declare function where( - predObj: $ObjMap - ): O => boolean; - - declare function whereEq( - predObj: O, - ...rest: Array - ): (o: $Shape) => boolean; - declare function whereEq( - predObj: O, - o: $Shape - ): boolean; - - declare function view(lens: Lens, val: T): V; - declare function view(lens: Lens): (val: T) => V; - - // *Function - declare var __: $npm$ramda$Placeholder; - - declare var T: (_: any) => true; - declare var F: (_: any) => false; - - declare function addIndex( - iterFn: (fn: (x: A) => B, xs: Array) => Array - ): (fn: (x: A, idx: number, xs: Array) => B, xs: Array) => Array; - - declare function always(x: T): (x: any) => T; - - - declare function ap( - fns: Array<(x: T) => V>, - ...rest: Array - ): (xs: Array) => Array; - declare function ap(fns: Array<(x: T) => V>, xs: Array): Array; - - declare function apply( - fn: (...args: Array) => V, - ...rest: Array - ): (xs: Array) => V; - declare function apply(fn: (...args: Array) => V, xs: Array): V; - - declare function applySpec< - V, - S, - A: Array, - T: NestedObject<(...args: A) => S> - >( - spec: T - ): (...args: A) => NestedObject; - - declare function applyTo( - a: A, - ...rest: Array - ): (fn: (x: A) => B) => B; - declare function applyTo(a: A, fn: (x: A) => B): B; - - declare function binary( - fn: (...args: Array) => T - ): (x: any, y: any) => T; - - declare function bind( - fn: (...args: Array) => any, - thisObj: T - ): (...args: Array) => any; - - declare function call( - fn: (...args: Array) => T, - ...args: Array - ): T; - - declare function comparator( - fn: BinaryPredicateFn - ): (x: T, y: T) => number; - - // TODO add tests - declare function construct( - ctor: Class> - ): (x: T) => GenericContructor; - - // TODO add tests - declare function constructN( - n: number, - ctor: Class> - ): (...args: any) => GenericContructorMulti; - - // TODO make less generic - declare function converge(after: Function, fns: Array): Function; - - declare function empty(x: T): T; - - declare function flip( - fn: (arg0: A, arg1: B) => TResult - ): CurriedFunction2; - declare function flip( - fn: (arg0: A, arg1: B, arg2: C) => TResult - ): ((arg0: B, arg1: A, ...rest: Array) => (arg2: C) => TResult) & - ((arg0: B, arg1: A, arg2: C) => TResult); - declare function flip( - fn: (arg0: A, arg1: B, arg2: C, arg3: D) => TResult - ): (( - arg1: B, - arg0: A, - ...rest: Array - ) => (arg2: C, arg3: D) => TResult) & - ((arg1: B, arg0: A, arg2: C, arg3: D) => TResult); - declare function flip( - fn: (arg0: A, arg1: B, arg2: C, arg3: D, arg4: E) => TResult - ): (( - arg1: B, - arg0: A, - ...rest: Array - ) => (arg2: C, arg3: D, arg4: E) => TResult) & - ((arg1: B, arg0: A, arg2: C, arg3: D, arg4: E) => TResult); - - declare function identity(x: T): T; - - declare function invoker( - arity: number, - name: $Enum - ): CurriedFunction2 & - CurriedFunction3 & - CurriedFunction4; - - declare function juxt( - fns: Array<(...args: Array) => T> - ): (...args: Array) => Array; - - // TODO lift - - // TODO liftN - - declare function memoize) => B>(fn: T): T; - - declare function memoizeWith( - keyFn: (x: A) => string, - ...rest: Array - ): (fn: (x: B) => B) => A; - declare function memoizeWith( - keyFn: (x: A) => string, - fn: (x: B) => B - ): A; - - declare function nAry( - arity: number, - fn: (...args: Array) => T - ): (...args: Array) => T; - - declare function nthArg(n: number): (...args: Array) => T; - - declare var o: (( - fn1: (b: B) => C, - ...rest: void[] - ) => ((fn2: (a: A) => B, ...rest: void[]) => (x: A) => C) & - ((fn2: (a: A) => B, x: A) => C)) & - (( - fn1: (b: B) => C, - fn2: (a: A) => B, - ...rest: void[] - ) => (x: A) => C) & - ((fn1: (b: B) => C, fn2: (a: A) => B, x: A) => C); - - declare function of(x: T): Array; - - declare function once) => B>(fn: T): T; - - declare var partial: Partial; - // TODO partialRight - // TODO pipeK - - declare function tap(fn: (x: T) => any, ...rest: Array): (x: T) => T; - declare function tap(fn: (x: T) => any, x: T): T; - - declare function tryCatch( - tryer: (a: A) => B - ): ((catcher: (e: E, a: A) => B) => (a: A) => B) & - ((catcher: (e: E, a: A) => B, a: A) => B); - declare function tryCatch( - tryer: (a: A) => B, - catcher: (e: E, a: A) => B - ): (a: A) => B; - declare function tryCatch( - tryer: (a: A) => B, - catcher: (e: E, a: A) => B, - a: A - ): B; - - declare function unapply( - fn: (xs: Array) => V - ): (...args: Array) => V; - - declare function unary(fn: (...args: Array) => T): (x: any) => T; - - declare var uncurryN: ((2, (A) => B => C) => (A, B) => C) & - ((3, (A) => B => C => D) => (A, B, C) => D) & - ((4, (A) => B => C => D => E) => (A, B, C, D) => E) & - (( - 5, - (A) => B => C => D => E => F - ) => (A, B, C, D, E) => F) & - (( - 6, - (A) => B => C => D => E => F => G - ) => (A, B, C, D, E, F) => G) & - (( - 7, - (A) => B => C => D => E => F => G => H - ) => (A, B, C, D, E, F, G) => H) & - (( - 8, - (A) => B => C => D => E => F => G => H => I - ) => (A, B, C, D, E, F, G, H) => I); - - // TODO useWith - - declare function wrap) => B>( - fn: F, - fn2: (fn: F, ...args: Array) => D - ): (...args: Array) => D; - - // *Logic - - declare function allPass( - fns: Array<(...args: Array) => boolean> - ): (...args: Array) => boolean; - - declare function and( - x: boolean, - ...rest: Array - ): (y: boolean) => boolean; - declare function and(x: boolean, y: boolean): boolean; - - declare function anyPass( - fns: Array<(...args: Array) => boolean> - ): (...args: Array) => boolean; - - declare function both( - x: (...args: Array) => boolean, - ...rest: Array - ): (y: (...args: Array) => boolean) => (...args: Array) => boolean; - declare function both( - x: (...args: Array) => boolean, - y: (...args: Array) => boolean - ): (...args: Array) => boolean; - - declare function complement( - x: (...args: Array) => boolean - ): (...args: Array) => boolean; - - declare function cond( - fns: Array<[(...args: Array) => boolean, (...args: Array) => B]> - ): (...args: Array) => B; - - declare function defaultTo( - d: T, - ...rest: Array - ): (x: ?V) => V | T; - declare function defaultTo(d: T, x: ?V): V | T; - - declare function either( - x: (...args: Array) => *, - ...rest: Array - ): (y: (...args: Array) => *) => (...args: Array) => *; - declare function either( - x: (...args: Array) => *, - y: (...args: Array) => * - ): (...args: Array) => *; - - declare function ifElse( - cond: (...args: Array) => boolean, - ...rest: Array - ): (( - f1: (...args: Array) => B, - ...rest: Array - ) => (f2: (...args: Array) => C) => (...args: Array) => B | C) & - (( - f1: (...args: Array) => B, - f2: (...args: Array) => C - ) => (...args: Array) => B | C); - declare function ifElse( - cond: (...args: Array) => boolean, - f1: (...args: Array) => B, - f2: (...args: Array) => C - ): (...args: Array) => B | C; - - declare function isEmpty(x: ?Array | Object | string): boolean; - - declare function not(x: boolean): boolean; - - declare function or(x: boolean, y: boolean): boolean; - declare function or(x: boolean): (y: boolean) => boolean; - - declare var pathSatisfies: CurriedFunction3< - UnaryPredicateFn, - string[], - Object, - boolean - >; - - declare function propSatisfies( - cond: (x: T) => boolean, - prop: string, - o: NestedObject - ): boolean; - declare function propSatisfies( - cond: (x: T) => boolean, - prop: string, - ...rest: Array - ): (o: NestedObject) => boolean; - declare function propSatisfies( - cond: (x: T) => boolean, - ...rest: Array - ): ((prop: string, ...rest: Array) => (o: NestedObject) => boolean) & - ((prop: string, o: NestedObject) => boolean); - - declare function unless( - pred: UnaryPredicateFn, - ...rest: Array - ): ((fn: (x: S) => V, ...rest: Array) => (x: T | S) => T | V) & - ((fn: (x: S) => V, x: T | S) => T | V); - declare function unless( - pred: UnaryPredicateFn, - fn: (x: S) => V, - ...rest: Array - ): (x: T | S) => V | T; - declare function unless( - pred: UnaryPredicateFn, - fn: (x: S) => V, - x: T | S - ): T | V; - - declare function until( - pred: UnaryPredicateFn, - ...rest: Array - ): ((fn: (x: T) => T, ...rest: Array) => (x: T) => T) & - ((fn: (x: T) => T, x: T) => T); - declare function until( - pred: UnaryPredicateFn, - fn: (x: T) => T, - ...rest: Array - ): (x: T) => T; - declare function until( - pred: UnaryPredicateFn, - fn: (x: T) => T, - x: T - ): T; - - declare function when( - pred: UnaryPredicateFn, - ...rest: Array - ): ((fn: (x: S) => V, ...rest: Array) => (x: T | S) => T | V) & - ((fn: (x: S) => V, x: T | S) => T | V); - declare function when( - pred: UnaryPredicateFn, - fn: (x: S) => V, - ...rest: Array - ): (x: T | S) => V | T; - declare function when( - pred: UnaryPredicateFn, - fn: (x: S) => V, - x: T | S - ): T | V; -} diff --git a/flow-typed/custom/yargs_v10.x.x.js b/flow-typed/custom/yargs_v10.x.x.js deleted file mode 100644 index e9f16eb3d..000000000 --- a/flow-typed/custom/yargs_v10.x.x.js +++ /dev/null @@ -1,259 +0,0 @@ -// flow-typed signature: d6f0db2a3d04a409b27a3514e5f1ab23 -// flow-typed version: da30fe6876/yargs_v10.x.x/flow_>=v0.54.x - -declare module "yargs" { - declare type Argv = { - _: Array, - $0: string, - [key: string]: any - }; - - declare type Options = $Shape<{ - alias: string | Array, - array: boolean, - boolean: boolean, - choices: Array, - coerce: (arg: mixed) => mixed, - config: boolean, - configParser: (configPath: string) => { [key: string]: mixed }, - conflicts: string | { [key: string]: string }, - count: boolean, - default: mixed, - defaultDescription: string, - demandOption: boolean | string, - desc: string, - describe: string, - description: string, - global: boolean, - group: string, - implies: string | { [key: string]: string }, - nargs: number, - normalize: boolean, - number: boolean, - requiresArg: boolean, - skipValidation: boolean, - string: boolean, - type: "array" | "boolean" | "count" | "number" | "string" - }>; - - declare type CommonModuleObject = {| - command?: string | Array, - aliases?: Array | string, - builder?: { [key: string]: Options } | ((yargsInstance: Yargs) => mixed), - handler?: (argv: Argv) => void - |}; - - declare type ModuleObjectDesc = {| - ...CommonModuleObject, - desc?: string | false - |}; - - declare type ModuleObjectDescribe = {| - ...CommonModuleObject, - describe?: string | false - |}; - - declare type ModuleObjectDescription = {| - ...CommonModuleObject, - description?: string | false - |}; - - declare type ModuleObject = - | ModuleObjectDesc - | ModuleObjectDescribe - | ModuleObjectDescription; - - declare class Yargs { - (args: Array): Yargs; - - alias(key: string, alias: string): this; - alias(alias: { [key: string]: string | Array }): this; - argv: Argv; - array(key: string | Array): this; - boolean(paramter: string | Array): this; - check(fn: (argv: Argv, options: Array) => ?boolean): this; - choices(key: string, allowed: Array): this; - choices(allowed: { [key: string]: Array }): this; - coerce(key: string, fn: (value: any) => mixed): this; - coerce(object: { [key: string]: (value: any) => mixed }): this; - coerce(keys: Array, fn: (value: any) => mixed): this; - - command( - cmd: string | Array, - desc: string | false, - builder?: { [key: string]: Options } | ((yargsInstance: Yargs) => mixed), - handler?: Function - ): this; - - command( - cmd: string | Array, - desc: string | false, - module: ModuleObject - ): this; - - command(module: ModuleObject): this; - - commandDir(dir: string, opts?: Object): this; - - completion( - cmd: string, - description?: string, - fn?: ( - current: string, - argv: Argv, - done: (competion: Array) => void - ) => ?(Array | Promise>) - ): this; - - config( - key?: string, - description?: string, - parseFn?: (configPath: string) => { [key: string]: mixed } - ): this; - config( - key: string, - parseFn?: (configPath: string) => { [key: string]: mixed } - ): this; - config(config: { [key: string]: mixed }): this; - - conflicts(key: string, value: string | Array): this; - conflicts(keys: { [key: string]: string | Array }): this; - - count(name: string): this; - - default(key: string, value: mixed, description?: string): this; - default(defaults: { [key: string]: mixed }): this; - - // Deprecated: use demandOption() and demandCommand() instead. - demand(key: string, msg?: string | boolean): this; - demand(count: number, max?: number, msg?: string | boolean): this; - - demandOption(key: string | Array, msg?: string | boolean): this; - - demandCommand(min?: number, minMsg?: string): this; - demandCommand( - min: number, - max: number, - minMsg?: string, - maxMsg?: string - ): this; - - describe(key: string, description: string): this; - describe(describeObject: { [key: string]: string }): this; - - detectLocale(shouldDetect: boolean): this; - - env(prefix?: string): this; - - epilog(text: string): this; - epilogue(text: string): this; - - example(cmd: string, desc: string): this; - - exitProcess(enable: boolean): this; - - fail(fn: (failureMessage: string, err: Error, yargs: Yargs) => mixed): this; - - getCompletion(args: Array, fn: () => void): this; - - global(globals: string | Array, isGlobal?: boolean): this; - - group(key: string | Array, groupName: string): this; - - help(option?: string, desc?: string): this; - - implies(key: string, value: string | Array): this; - implies(keys: { [key: string]: string | Array }): this; - - locale( - locale: | "de" - | "en" - | "es" - | "fr" - | "hi" - | "hu" - | "id" - | "it" - | "ja" - | "ko" - | "nb" - | "pirate" - | "pl" - | "pt" - | "pt_BR" - | "ru" - | "th" - | "tr" - | "zh_CN" - ): this; - locale(): string; - - nargs(key: string, count: number): this; - - normalize(key: string): this; - - number(key: string | Array): this; - - option(key: string, options?: Options): this; - option(optionMap: { [key: string]: Options }): this; - - options(key: string, options?: Options): this; - options(optionMap: { [key: string]: Options }): this; - - parse( - args?: string | Array, - context?: { [key: string]: mixed }, - parseCallback?: (err: Error, argv: Argv, output?: string) => void - ): Argv; - parse( - args?: string | Array, - parseCallback?: (err: Error, argv: Argv, output?: string) => void - ): Argv; - - pkgConf(key: string, cwd?: string): this; - - positional(message: string, opts?: Object): this; - - recommendCommands(): this; - - // Alias of demand() - require(key: string, msg: string | boolean): this; - require(count: number, max?: number, msg?: string | boolean): this; - - requiresArg(key: string | Array): this; - - reset(): this; - - showCompletionScript(): this; - - showHelp(consoleLevel?: "error" | "warn" | "log"): this; - - showHelpOnFail(enable: boolean, message?: string): this; - - strict(): this; - - skipValidation(key: string): this; - - strict(global?: boolean): this; - - string(key: string | Array): this; - - updateLocale(obj: { [key: string]: string }): this; - updateStrings(obj: { [key: string]: string }): this; - - usage(message: string, opts?: { [key: string]: Options }): this; - - version(): this; - version(version: string): this; - version(option: string | (() => string), version: string): this; - version( - option: string | (() => string), - description: string | (() => string), - version: string - ): this; - - wrap(columns: number | null): this; - } - - declare module.exports: Yargs; -} diff --git a/flow-typed/npm/babel-cli_vx.x.x.js b/flow-typed/npm/babel-cli_vx.x.x.js deleted file mode 100644 index ff6e02620..000000000 --- a/flow-typed/npm/babel-cli_vx.x.x.js +++ /dev/null @@ -1,108 +0,0 @@ -// flow-typed signature: 2be8d574e9f7030854fc60dac99e21af -// flow-typed version: <>/babel-cli_v^6.24.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-cli' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-cli' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-cli/bin/babel-doctor' { - declare module.exports: any; -} - -declare module 'babel-cli/bin/babel-external-helpers' { - declare module.exports: any; -} - -declare module 'babel-cli/bin/babel-node' { - declare module.exports: any; -} - -declare module 'babel-cli/bin/babel' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/_babel-node' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel-external-helpers' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel-node' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel/dir' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel/file' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel/index' { - declare module.exports: any; -} - -declare module 'babel-cli/lib/babel/util' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-cli/bin/babel-doctor.js' { - declare module.exports: $Exports<'babel-cli/bin/babel-doctor'>; -} -declare module 'babel-cli/bin/babel-external-helpers.js' { - declare module.exports: $Exports<'babel-cli/bin/babel-external-helpers'>; -} -declare module 'babel-cli/bin/babel-node.js' { - declare module.exports: $Exports<'babel-cli/bin/babel-node'>; -} -declare module 'babel-cli/bin/babel.js' { - declare module.exports: $Exports<'babel-cli/bin/babel'>; -} -declare module 'babel-cli/index' { - declare module.exports: $Exports<'babel-cli'>; -} -declare module 'babel-cli/index.js' { - declare module.exports: $Exports<'babel-cli'>; -} -declare module 'babel-cli/lib/_babel-node.js' { - declare module.exports: $Exports<'babel-cli/lib/_babel-node'>; -} -declare module 'babel-cli/lib/babel-external-helpers.js' { - declare module.exports: $Exports<'babel-cli/lib/babel-external-helpers'>; -} -declare module 'babel-cli/lib/babel-node.js' { - declare module.exports: $Exports<'babel-cli/lib/babel-node'>; -} -declare module 'babel-cli/lib/babel/dir.js' { - declare module.exports: $Exports<'babel-cli/lib/babel/dir'>; -} -declare module 'babel-cli/lib/babel/file.js' { - declare module.exports: $Exports<'babel-cli/lib/babel/file'>; -} -declare module 'babel-cli/lib/babel/index.js' { - declare module.exports: $Exports<'babel-cli/lib/babel/index'>; -} -declare module 'babel-cli/lib/babel/util.js' { - declare module.exports: $Exports<'babel-cli/lib/babel/util'>; -} diff --git a/flow-typed/npm/babel-core_vx.x.x.js b/flow-typed/npm/babel-core_vx.x.x.js deleted file mode 100644 index e6a9eb5a4..000000000 --- a/flow-typed/npm/babel-core_vx.x.x.js +++ /dev/null @@ -1,227 +0,0 @@ -// flow-typed signature: 520d2aa8f520a3733ab38dc55fed395a -// flow-typed version: <>/babel-core_v^6.25.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-core' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-core' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-core/lib/api/browser' { - declare module.exports: any; -} - -declare module 'babel-core/lib/api/node' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/get-possible-plugin-names' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/get-possible-preset-names' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/merge' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/normalize-ast' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/resolve-from-possible-names' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/resolve-plugin' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/resolve-preset' { - declare module.exports: any; -} - -declare module 'babel-core/lib/helpers/resolve' { - declare module.exports: any; -} - -declare module 'babel-core/lib/store' { - declare module.exports: any; -} - -declare module 'babel-core/lib/tools/build-external-helpers' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/index' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/logger' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/metadata' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/build-config-chain' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/config' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/index' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/option-manager' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/parsers' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/file/options/removed' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/internal-plugins/block-hoist' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/internal-plugins/shadow-functions' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/pipeline' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/plugin-pass' { - declare module.exports: any; -} - -declare module 'babel-core/lib/transformation/plugin' { - declare module.exports: any; -} - -declare module 'babel-core/lib/util' { - declare module.exports: any; -} - -declare module 'babel-core/register' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-core/index' { - declare module.exports: $Exports<'babel-core'>; -} -declare module 'babel-core/index.js' { - declare module.exports: $Exports<'babel-core'>; -} -declare module 'babel-core/lib/api/browser.js' { - declare module.exports: $Exports<'babel-core/lib/api/browser'>; -} -declare module 'babel-core/lib/api/node.js' { - declare module.exports: $Exports<'babel-core/lib/api/node'>; -} -declare module 'babel-core/lib/helpers/get-possible-plugin-names.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/get-possible-plugin-names'>; -} -declare module 'babel-core/lib/helpers/get-possible-preset-names.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/get-possible-preset-names'>; -} -declare module 'babel-core/lib/helpers/merge.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/merge'>; -} -declare module 'babel-core/lib/helpers/normalize-ast.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/normalize-ast'>; -} -declare module 'babel-core/lib/helpers/resolve-from-possible-names.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/resolve-from-possible-names'>; -} -declare module 'babel-core/lib/helpers/resolve-plugin.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/resolve-plugin'>; -} -declare module 'babel-core/lib/helpers/resolve-preset.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/resolve-preset'>; -} -declare module 'babel-core/lib/helpers/resolve.js' { - declare module.exports: $Exports<'babel-core/lib/helpers/resolve'>; -} -declare module 'babel-core/lib/store.js' { - declare module.exports: $Exports<'babel-core/lib/store'>; -} -declare module 'babel-core/lib/tools/build-external-helpers.js' { - declare module.exports: $Exports<'babel-core/lib/tools/build-external-helpers'>; -} -declare module 'babel-core/lib/transformation/file/index.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/index'>; -} -declare module 'babel-core/lib/transformation/file/logger.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/logger'>; -} -declare module 'babel-core/lib/transformation/file/metadata.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/metadata'>; -} -declare module 'babel-core/lib/transformation/file/options/build-config-chain.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/build-config-chain'>; -} -declare module 'babel-core/lib/transformation/file/options/config.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/config'>; -} -declare module 'babel-core/lib/transformation/file/options/index.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/index'>; -} -declare module 'babel-core/lib/transformation/file/options/option-manager.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/option-manager'>; -} -declare module 'babel-core/lib/transformation/file/options/parsers.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/parsers'>; -} -declare module 'babel-core/lib/transformation/file/options/removed.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/file/options/removed'>; -} -declare module 'babel-core/lib/transformation/internal-plugins/block-hoist.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/internal-plugins/block-hoist'>; -} -declare module 'babel-core/lib/transformation/internal-plugins/shadow-functions.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/internal-plugins/shadow-functions'>; -} -declare module 'babel-core/lib/transformation/pipeline.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/pipeline'>; -} -declare module 'babel-core/lib/transformation/plugin-pass.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/plugin-pass'>; -} -declare module 'babel-core/lib/transformation/plugin.js' { - declare module.exports: $Exports<'babel-core/lib/transformation/plugin'>; -} -declare module 'babel-core/lib/util.js' { - declare module.exports: $Exports<'babel-core/lib/util'>; -} -declare module 'babel-core/register.js' { - declare module.exports: $Exports<'babel-core/register'>; -} diff --git a/flow-typed/npm/babel-eslint_vx.x.x.js b/flow-typed/npm/babel-eslint_vx.x.x.js deleted file mode 100644 index 9bb9aa691..000000000 --- a/flow-typed/npm/babel-eslint_vx.x.x.js +++ /dev/null @@ -1,80 +0,0 @@ -// flow-typed signature: fb9050b753124adf69b920326736cddb -// flow-typed version: <>/babel-eslint_v^7.2.3/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-eslint' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-eslint' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-eslint/babylon-to-espree/attachComments' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/convertComments' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/convertTemplateType' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/index' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/toAST' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/toToken' { - declare module.exports: any; -} - -declare module 'babel-eslint/babylon-to-espree/toTokens' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-eslint/babylon-to-espree/attachComments.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/attachComments'>; -} -declare module 'babel-eslint/babylon-to-espree/convertComments.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/convertComments'>; -} -declare module 'babel-eslint/babylon-to-espree/convertTemplateType.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/convertTemplateType'>; -} -declare module 'babel-eslint/babylon-to-espree/index.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/index'>; -} -declare module 'babel-eslint/babylon-to-espree/toAST.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toAST'>; -} -declare module 'babel-eslint/babylon-to-espree/toToken.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toToken'>; -} -declare module 'babel-eslint/babylon-to-espree/toTokens.js' { - declare module.exports: $Exports<'babel-eslint/babylon-to-espree/toTokens'>; -} -declare module 'babel-eslint/index' { - declare module.exports: $Exports<'babel-eslint'>; -} -declare module 'babel-eslint/index.js' { - declare module.exports: $Exports<'babel-eslint'>; -} diff --git a/flow-typed/npm/babel-jest_vx.x.x.js b/flow-typed/npm/babel-jest_vx.x.x.js deleted file mode 100644 index 9752a2612..000000000 --- a/flow-typed/npm/babel-jest_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: 9513ece6a38cfbf075893a25afcdcf62 -// flow-typed version: <>/babel-jest_v^20.0.3/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-jest' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-jest' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-jest/build/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-jest/build/index.js' { - declare module.exports: $Exports<'babel-jest/build/index'>; -} diff --git a/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js b/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js deleted file mode 100644 index 67d643d72..000000000 --- a/flow-typed/npm/babel-plugin-syntax-async-functions_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: 8df6b70600252a1a7e837764b6331b47 -// flow-typed version: <>/babel-plugin-syntax-async-functions_v^6.13.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-plugin-syntax-async-functions' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-plugin-syntax-async-functions' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-plugin-syntax-async-functions/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-plugin-syntax-async-functions/lib/index.js' { - declare module.exports: $Exports<'babel-plugin-syntax-async-functions/lib/index'>; -} diff --git a/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js b/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js deleted file mode 100644 index 906c13989..000000000 --- a/flow-typed/npm/babel-plugin-transform-flow-strip-types_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: 0449f740a9cee2d12c5e48bc2cd2b245 -// flow-typed version: <>/babel-plugin-transform-flow-strip-types_v^6.18.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-plugin-transform-flow-strip-types' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-plugin-transform-flow-strip-types' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-plugin-transform-flow-strip-types/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-plugin-transform-flow-strip-types/lib/index.js' { - declare module.exports: $Exports<'babel-plugin-transform-flow-strip-types/lib/index'>; -} diff --git a/flow-typed/npm/babel-plugin-transform-object-rest-spread_vx.x.x.js b/flow-typed/npm/babel-plugin-transform-object-rest-spread_vx.x.x.js deleted file mode 100644 index f3a04e3a5..000000000 --- a/flow-typed/npm/babel-plugin-transform-object-rest-spread_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: 68032a0f1edfd9671ff589311bf27cda -// flow-typed version: <>/babel-plugin-transform-object-rest-spread_v^6.23.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-plugin-transform-object-rest-spread' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-plugin-transform-object-rest-spread' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-plugin-transform-object-rest-spread/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-plugin-transform-object-rest-spread/lib/index.js' { - declare module.exports: $Exports<'babel-plugin-transform-object-rest-spread/lib/index'>; -} diff --git a/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js b/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js deleted file mode 100644 index 4fc0d68c6..000000000 --- a/flow-typed/npm/babel-plugin-transform-regenerator_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: fffb45a8c4b340658b11d531212778d5 -// flow-typed version: <>/babel-plugin-transform-regenerator_v^6.24.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-plugin-transform-regenerator' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-plugin-transform-regenerator' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-plugin-transform-regenerator/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-plugin-transform-regenerator/lib/index.js' { - declare module.exports: $Exports<'babel-plugin-transform-regenerator/lib/index'>; -} diff --git a/flow-typed/npm/babel-polyfill_vx.x.x.js b/flow-typed/npm/babel-polyfill_vx.x.x.js deleted file mode 100644 index 670114a05..000000000 --- a/flow-typed/npm/babel-polyfill_vx.x.x.js +++ /dev/null @@ -1,67 +0,0 @@ -// flow-typed signature: dd099d709aa9ab8ed935f00dfca8d54f -// flow-typed version: <>/babel-polyfill_v^6.16.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-polyfill' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-polyfill' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-polyfill/browser' { - declare module.exports: any; -} - -declare module 'babel-polyfill/dist/polyfill' { - declare module.exports: any; -} - -declare module 'babel-polyfill/dist/polyfill.min' { - declare module.exports: any; -} - -declare module 'babel-polyfill/lib/index' { - declare module.exports: any; -} - -declare module 'babel-polyfill/scripts/postpublish' { - declare module.exports: any; -} - -declare module 'babel-polyfill/scripts/prepublish' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-polyfill/browser.js' { - declare module.exports: $Exports<'babel-polyfill/browser'>; -} -declare module 'babel-polyfill/dist/polyfill.js' { - declare module.exports: $Exports<'babel-polyfill/dist/polyfill'>; -} -declare module 'babel-polyfill/dist/polyfill.min.js' { - declare module.exports: $Exports<'babel-polyfill/dist/polyfill.min'>; -} -declare module 'babel-polyfill/lib/index.js' { - declare module.exports: $Exports<'babel-polyfill/lib/index'>; -} -declare module 'babel-polyfill/scripts/postpublish.js' { - declare module.exports: $Exports<'babel-polyfill/scripts/postpublish'>; -} -declare module 'babel-polyfill/scripts/prepublish.js' { - declare module.exports: $Exports<'babel-polyfill/scripts/prepublish'>; -} diff --git a/flow-typed/npm/babel-preset-es2015_vx.x.x.js b/flow-typed/npm/babel-preset-es2015_vx.x.x.js deleted file mode 100644 index 07e1cda29..000000000 --- a/flow-typed/npm/babel-preset-es2015_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: cc52b4874d48c8e5eeafb8fade9fbdbd -// flow-typed version: <>/babel-preset-es2015_v^6.24.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'babel-preset-es2015' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'babel-preset-es2015' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'babel-preset-es2015/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'babel-preset-es2015/lib/index.js' { - declare module.exports: $Exports<'babel-preset-es2015/lib/index'>; -} diff --git a/flow-typed/npm/body-parser_v1.x.x.js b/flow-typed/npm/body-parser_v1.x.x.js deleted file mode 100644 index 15d116651..000000000 --- a/flow-typed/npm/body-parser_v1.x.x.js +++ /dev/null @@ -1,41 +0,0 @@ -// flow-typed signature: f39e87ae093403a8f3c789273ccddbf6 -// flow-typed version: 7e7c66e29a/body-parser_v1.x.x/flow_>=v0.30.x - -declare type bodyParser$Options = { - inflate?: boolean; - limit?: number | string; - type?: string | string[] | ((req: express$Request) => any); - verify?: (req: express$Request, res: express$Response, buf: Buffer, encoding: string) => void; -}; - -declare type bodyParser$OptionsText = bodyParser$Options & { - reviever?: (key: string, value: any) => any; - strict?: boolean; -}; - -declare type bodyParser$OptionsJson = bodyParser$Options & { - reviever?: (key: string, value: any) => any; - strict?: boolean; -}; - -declare type bodyParser$OptionsUrlencoded = bodyParser$Options & { - extended?: boolean; - parameterLimit?: number; -}; - -declare module "body-parser" { - - declare type Options = bodyParser$Options; - declare type OptionsText = bodyParser$OptionsText; - declare type OptionsJson = bodyParser$OptionsJson; - declare type OptionsUrlencoded = bodyParser$OptionsUrlencoded; - - declare function json(options?: OptionsJson): express$Middleware; - - declare function raw(options?: Options): express$Middleware; - - declare function text(options?: OptionsText): express$Middleware; - - declare function urlencoded(options?: OptionsUrlencoded): express$Middleware; - -} diff --git a/flow-typed/npm/chalk_v1.x.x.js b/flow-typed/npm/chalk_v1.x.x.js deleted file mode 100644 index a10a34eae..000000000 --- a/flow-typed/npm/chalk_v1.x.x.js +++ /dev/null @@ -1,114 +0,0 @@ -// flow-typed signature: 9d7ebf432fe5436b8912d014b367d934 -// flow-typed version: b059774d08/chalk_v1.x.x/flow_>=v0.21.x - -type $npm$chalk$StyleElement = { - open: string; - close: string; -}; - -type $npm$chalk$Chain = $npm$chalk$Style & (...text: any[]) => string; - -type $npm$chalk$Style = { - // General - reset: $npm$chalk$Chain; - bold: $npm$chalk$Chain; - dim: $npm$chalk$Chain; - italic: $npm$chalk$Chain; - underline: $npm$chalk$Chain; - inverse: $npm$chalk$Chain; - strikethrough: $npm$chalk$Chain; - - // Text colors - black: $npm$chalk$Chain; - red: $npm$chalk$Chain; - green: $npm$chalk$Chain; - yellow: $npm$chalk$Chain; - blue: $npm$chalk$Chain; - magenta: $npm$chalk$Chain; - cyan: $npm$chalk$Chain; - white: $npm$chalk$Chain; - gray: $npm$chalk$Chain; - grey: $npm$chalk$Chain; - - // Background colors - bgBlack: $npm$chalk$Chain; - bgRed: $npm$chalk$Chain; - bgGreen: $npm$chalk$Chain; - bgYellow: $npm$chalk$Chain; - bgBlue: $npm$chalk$Chain; - bgMagenta: $npm$chalk$Chain; - bgCyan: $npm$chalk$Chain; - bgWhite: $npm$chalk$Chain; -}; - -type $npm$chalk$StyleMap = { - // General - reset: $npm$chalk$StyleElement; - bold: $npm$chalk$StyleElement; - dim: $npm$chalk$StyleElement; - italic: $npm$chalk$StyleElement; - underline: $npm$chalk$StyleElement; - inverse: $npm$chalk$StyleElement; - strikethrough: $npm$chalk$StyleElement; - - // Text colors - black: $npm$chalk$StyleElement; - red: $npm$chalk$StyleElement; - green: $npm$chalk$StyleElement; - yellow: $npm$chalk$StyleElement; - blue: $npm$chalk$StyleElement; - magenta: $npm$chalk$StyleElement; - cyan: $npm$chalk$StyleElement; - white: $npm$chalk$StyleElement; - gray: $npm$chalk$StyleElement; - - // Background colors - bgBlack: $npm$chalk$StyleElement; - bgRed: $npm$chalk$StyleElement; - bgGreen: $npm$chalk$StyleElement; - bgYellow: $npm$chalk$StyleElement; - bgBlue: $npm$chalk$StyleElement; - bgMagenta: $npm$chalk$StyleElement; - bgCyan: $npm$chalk$StyleElement; - bgWhite: $npm$chalk$StyleElement; -}; - -declare module "chalk" { - declare var enabled: boolean; - declare var supportsColor: boolean; - declare var styles: $npm$chalk$StyleMap; - - declare function stripColor(value: string): any; - declare function hasColor(str: string): boolean; - - // General - declare var reset: $npm$chalk$Chain; - declare var bold: $npm$chalk$Chain; - declare var dim: $npm$chalk$Chain; - declare var italic: $npm$chalk$Chain; - declare var underline: $npm$chalk$Chain; - declare var inverse: $npm$chalk$Chain; - declare var strikethrough: $npm$chalk$Chain; - - // Text colors - declare var black: $npm$chalk$Chain; - declare var red: $npm$chalk$Chain; - declare var green: $npm$chalk$Chain; - declare var yellow: $npm$chalk$Chain; - declare var blue: $npm$chalk$Chain; - declare var magenta: $npm$chalk$Chain; - declare var cyan: $npm$chalk$Chain; - declare var white: $npm$chalk$Chain; - declare var gray: $npm$chalk$Chain; - declare var grey: $npm$chalk$Chain; - - // Background colors - declare var bgBlack: $npm$chalk$Chain; - declare var bgRed: $npm$chalk$Chain; - declare var bgGreen: $npm$chalk$Chain; - declare var bgYellow: $npm$chalk$Chain; - declare var bgBlue: $npm$chalk$Chain; - declare var bgMagenta: $npm$chalk$Chain; - declare var bgCyan: $npm$chalk$Chain; - declare var bgWhite: $npm$chalk$Chain; -} diff --git a/flow-typed/npm/co_vx.x.x.js b/flow-typed/npm/co_vx.x.x.js deleted file mode 100644 index acf574f9f..000000000 --- a/flow-typed/npm/co_vx.x.x.js +++ /dev/null @@ -1,33 +0,0 @@ -// flow-typed signature: a8d2ff136fb520381a9b5cf180f7943f -// flow-typed version: <>/co_v^4.6.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'co' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'co' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ - - -// Filename aliases -declare module 'co/index' { - declare module.exports: $Exports<'co'>; -} -declare module 'co/index.js' { - declare module.exports: $Exports<'co'>; -} diff --git a/flow-typed/npm/eslint-plugin-flow-vars_vx.x.x.js b/flow-typed/npm/eslint-plugin-flow-vars_vx.x.x.js deleted file mode 100644 index abd254c53..000000000 --- a/flow-typed/npm/eslint-plugin-flow-vars_vx.x.x.js +++ /dev/null @@ -1,45 +0,0 @@ -// flow-typed signature: 6ba5732cbc7eee9fa0b0290482733afa -// flow-typed version: <>/eslint-plugin-flow-vars_v^0.5.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'eslint-plugin-flow-vars' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'eslint-plugin-flow-vars' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'eslint-plugin-flow-vars/define-flow-type' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flow-vars/use-flow-type' { - declare module.exports: any; -} - -// Filename aliases -declare module 'eslint-plugin-flow-vars/define-flow-type.js' { - declare module.exports: $Exports<'eslint-plugin-flow-vars/define-flow-type'>; -} -declare module 'eslint-plugin-flow-vars/index' { - declare module.exports: $Exports<'eslint-plugin-flow-vars'>; -} -declare module 'eslint-plugin-flow-vars/index.js' { - declare module.exports: $Exports<'eslint-plugin-flow-vars'>; -} -declare module 'eslint-plugin-flow-vars/use-flow-type.js' { - declare module.exports: $Exports<'eslint-plugin-flow-vars/use-flow-type'>; -} diff --git a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js b/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js deleted file mode 100644 index 3baea4a55..000000000 --- a/flow-typed/npm/eslint-plugin-flowtype_vx.x.x.js +++ /dev/null @@ -1,291 +0,0 @@ -// flow-typed signature: 900c2fde9cfa8ecb03cf8b50fd21e783 -// flow-typed version: <>/eslint-plugin-flowtype_v^2.25.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'eslint-plugin-flowtype' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'eslint-plugin-flowtype' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'eslint-plugin-flowtype/bin/readmeAssertions' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/index' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/semi' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/sortKeys' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/useFlowType' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/rules/validSyntax' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/index' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/quoteName' { - declare module.exports: any; -} - -declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers' { - declare module.exports: any; -} - -// Filename aliases -declare module 'eslint-plugin-flowtype/bin/readmeAssertions.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/bin/readmeAssertions'>; -} -declare module 'eslint-plugin-flowtype/dist/index.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/index'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/booleanStyle.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/booleanStyle'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/defineFlowType.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/defineFlowType'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/delimiterDangle.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/delimiterDangle'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/genericSpacing.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/genericSpacing'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/noDupeKeys.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noDupeKeys'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/noWeakTypes.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/noWeakTypes'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/objectTypeDelimiter'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/requireParameterType.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireParameterType'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/requireReturnType.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireReturnType'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/requireValidFileAnnotation'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/semi.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/semi'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/sortKeys.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/sortKeys'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceAfterTypeColon'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeGenericBracket'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/spaceBeforeTypeColon'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateFunctions'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeIndexer'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateObjectTypeProperty'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateReturnType'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypeCastExpression'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/evaluateTypical'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/index'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeColonSpacing/reporter'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/typeIdMatch.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/typeIdMatch'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/unionIntersectionSpacing'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/useFlowType.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/useFlowType'>; -} -declare module 'eslint-plugin-flowtype/dist/rules/validSyntax.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/rules/validSyntax'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/getParameterName.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getParameterName'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenAfterParens'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/getTokenBeforeParens'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/index.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/index'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFile.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFile'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/isFlowFileAnnotation'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/iterateFunctionNodes'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/quoteName.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/quoteName'>; -} -declare module 'eslint-plugin-flowtype/dist/utilities/spacingFixers.js' { - declare module.exports: $Exports<'eslint-plugin-flowtype/dist/utilities/spacingFixers'>; -} diff --git a/flow-typed/npm/eslint-plugin-graphql_vx.x.x.js b/flow-typed/npm/eslint-plugin-graphql_vx.x.x.js deleted file mode 100644 index 16c288e39..000000000 --- a/flow-typed/npm/eslint-plugin-graphql_vx.x.x.js +++ /dev/null @@ -1,32 +0,0 @@ -// flow-typed signature: 0da12411f82771a1612bbc58863a85b8 -// flow-typed version: <>/eslint-plugin-graphql_v^0.2.7/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'eslint-plugin-graphql' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'eslint-plugin-graphql' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'eslint-plugin-graphql/lib/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'eslint-plugin-graphql/lib/index.js' { - declare module.exports: $Exports<'eslint-plugin-graphql/lib/index'>; -} diff --git a/flow-typed/npm/eslint_vx.x.x.js b/flow-typed/npm/eslint_vx.x.x.js deleted file mode 100644 index 5732a28d0..000000000 --- a/flow-typed/npm/eslint_vx.x.x.js +++ /dev/null @@ -1,2349 +0,0 @@ -// flow-typed signature: 6256d34ba4171e845c606f6d4251b90d -// flow-typed version: <>/eslint_v^4.0.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'eslint' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'eslint' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'eslint/bin/eslint' { - declare module.exports: any; -} - -declare module 'eslint/conf/default-cli-options' { - declare module.exports: any; -} - -declare module 'eslint/conf/default-config-options' { - declare module.exports: any; -} - -declare module 'eslint/conf/environments' { - declare module.exports: any; -} - -declare module 'eslint/conf/eslint-all' { - declare module.exports: any; -} - -declare module 'eslint/conf/eslint-recommended' { - declare module.exports: any; -} - -declare module 'eslint/lib/api' { - declare module.exports: any; -} - -declare module 'eslint/lib/ast-utils' { - declare module.exports: any; -} - -declare module 'eslint/lib/cli-engine' { - declare module.exports: any; -} - -declare module 'eslint/lib/cli' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/code-path-analyzer' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/code-path-segment' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/code-path-state' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/code-path' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/debug-helpers' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/fork-context' { - declare module.exports: any; -} - -declare module 'eslint/lib/code-path-analysis/id-generator' { - declare module.exports: any; -} - -declare module 'eslint/lib/config' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/autoconfig' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/config-file' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/config-initializer' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/config-ops' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/config-rule' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/config-validator' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/environments' { - declare module.exports: any; -} - -declare module 'eslint/lib/config/plugins' { - declare module.exports: any; -} - -declare module 'eslint/lib/file-finder' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/checkstyle' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/codeframe' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/compact' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/html' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/jslint-xml' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/json' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/junit' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/stylish' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/table' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/tap' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/unix' { - declare module.exports: any; -} - -declare module 'eslint/lib/formatters/visualstudio' { - declare module.exports: any; -} - -declare module 'eslint/lib/ignored-paths' { - declare module.exports: any; -} - -declare module 'eslint/lib/internal-rules/internal-consistent-docs-description' { - declare module.exports: any; -} - -declare module 'eslint/lib/internal-rules/internal-no-invalid-meta' { - declare module.exports: any; -} - -declare module 'eslint/lib/linter' { - declare module.exports: any; -} - -declare module 'eslint/lib/load-rules' { - declare module.exports: any; -} - -declare module 'eslint/lib/logging' { - declare module.exports: any; -} - -declare module 'eslint/lib/options' { - declare module.exports: any; -} - -declare module 'eslint/lib/rule-context' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/accessor-pairs' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/array-bracket-newline' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/array-bracket-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/array-callback-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/array-element-newline' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/arrow-body-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/arrow-parens' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/arrow-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/block-scoped-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/block-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/brace-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/callback-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/camelcase' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/capitalized-comments' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/class-methods-use-this' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/comma-dangle' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/comma-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/comma-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/complexity' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/computed-property-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/consistent-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/consistent-this' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/constructor-super' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/curly' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/default-case' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/dot-location' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/dot-notation' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/eol-last' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/eqeqeq' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/for-direction' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/func-call-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/func-name-matching' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/func-names' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/func-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/generator-star-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/global-require' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/guard-for-in' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/handle-callback-err' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/id-blacklist' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/id-length' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/id-match' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/indent-legacy' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/indent' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/init-declarations' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/jsx-quotes' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/key-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/keyword-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/line-comment-position' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/linebreak-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/lines-around-comment' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/lines-around-directive' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-depth' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-len' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-lines' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-nested-callbacks' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-params' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-statements-per-line' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/max-statements' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/multiline-ternary' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/new-cap' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/new-parens' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/newline-after-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/newline-before-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/newline-per-chained-call' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-alert' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-array-constructor' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-await-in-loop' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-bitwise' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-buffer-constructor' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-caller' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-case-declarations' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-catch-shadow' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-class-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-compare-neg-zero' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-cond-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-confusing-arrow' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-console' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-const-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-constant-condition' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-continue' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-control-regex' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-debugger' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-delete-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-div-regex' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-dupe-args' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-dupe-class-members' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-dupe-keys' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-duplicate-case' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-duplicate-imports' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-else-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-empty-character-class' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-empty-function' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-empty-pattern' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-empty' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-eq-null' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-eval' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-ex-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extend-native' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extra-bind' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extra-boolean-cast' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extra-label' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extra-parens' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-extra-semi' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-fallthrough' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-floating-decimal' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-func-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-global-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-implicit-coercion' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-implicit-globals' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-implied-eval' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-inline-comments' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-inner-declarations' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-invalid-regexp' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-invalid-this' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-irregular-whitespace' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-iterator' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-label-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-labels' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-lone-blocks' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-lonely-if' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-loop-func' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-magic-numbers' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-mixed-operators' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-mixed-requires' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-mixed-spaces-and-tabs' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-multi-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-multi-spaces' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-multi-str' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-multiple-empty-lines' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-native-reassign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-negated-condition' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-negated-in-lhs' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-nested-ternary' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new-func' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new-object' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new-require' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new-symbol' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new-wrappers' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-new' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-obj-calls' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-octal-escape' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-octal' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-param-reassign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-path-concat' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-plusplus' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-process-env' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-process-exit' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-proto' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-prototype-builtins' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-redeclare' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-regex-spaces' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-restricted-globals' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-restricted-imports' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-restricted-modules' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-restricted-properties' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-restricted-syntax' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-return-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-return-await' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-script-url' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-self-assign' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-self-compare' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-sequences' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-shadow-restricted-names' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-shadow' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-spaced-func' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-sparse-arrays' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-sync' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-tabs' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-template-curly-in-string' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-ternary' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-this-before-super' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-throw-literal' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-trailing-spaces' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-undef-init' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-undef' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-undefined' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-underscore-dangle' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unexpected-multiline' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unmodified-loop-condition' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unneeded-ternary' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unreachable' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unsafe-finally' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unsafe-negation' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unused-expressions' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unused-labels' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-unused-vars' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-use-before-define' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-call' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-computed-key' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-concat' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-constructor' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-escape' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-rename' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-useless-return' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-void' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-warning-comments' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-whitespace-before-property' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/no-with' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/nonblock-statement-body-position' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/object-curly-newline' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/object-curly-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/object-property-newline' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/object-shorthand' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/one-var-declaration-per-line' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/one-var' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/operator-assignment' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/operator-linebreak' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/padded-blocks' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/padding-line-between-statements' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-arrow-callback' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-const' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-destructuring' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-numeric-literals' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-promise-reject-errors' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-reflect' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-rest-params' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-spread' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/prefer-template' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/quote-props' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/quotes' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/radix' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/require-await' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/require-jsdoc' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/require-yield' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/rest-spread-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/semi-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/semi-style' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/semi' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/sort-imports' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/sort-keys' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/sort-vars' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/space-before-blocks' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/space-before-function-paren' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/space-in-parens' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/space-infix-ops' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/space-unary-ops' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/spaced-comment' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/strict' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/switch-colon-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/symbol-description' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/template-curly-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/template-tag-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/unicode-bom' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/use-isnan' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/valid-jsdoc' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/valid-typeof' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/vars-on-top' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/wrap-iife' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/wrap-regex' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/yield-star-spacing' { - declare module.exports: any; -} - -declare module 'eslint/lib/rules/yoda' { - declare module.exports: any; -} - -declare module 'eslint/lib/testers/event-generator-tester' { - declare module.exports: any; -} - -declare module 'eslint/lib/testers/rule-tester' { - declare module.exports: any; -} - -declare module 'eslint/lib/timing' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/backward-token-comment-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/backward-token-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/cursors' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/decorative-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/filter-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/forward-token-comment-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/forward-token-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/index' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/limit-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/padded-token-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/skip-cursor' { - declare module.exports: any; -} - -declare module 'eslint/lib/token-store/utils' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/fix-tracker' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/glob-util' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/glob' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/hash' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/keywords' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/module-resolver' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/node-event-generator' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/npm-util' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/path-util' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/patterns/letters' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/rule-fixer' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/source-code-fixer' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/source-code-util' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/source-code' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/traverser' { - declare module.exports: any; -} - -declare module 'eslint/lib/util/xml-escape' { - declare module.exports: any; -} - -// Filename aliases -declare module 'eslint/bin/eslint.js' { - declare module.exports: $Exports<'eslint/bin/eslint'>; -} -declare module 'eslint/conf/default-cli-options.js' { - declare module.exports: $Exports<'eslint/conf/default-cli-options'>; -} -declare module 'eslint/conf/default-config-options.js' { - declare module.exports: $Exports<'eslint/conf/default-config-options'>; -} -declare module 'eslint/conf/environments.js' { - declare module.exports: $Exports<'eslint/conf/environments'>; -} -declare module 'eslint/conf/eslint-all.js' { - declare module.exports: $Exports<'eslint/conf/eslint-all'>; -} -declare module 'eslint/conf/eslint-recommended.js' { - declare module.exports: $Exports<'eslint/conf/eslint-recommended'>; -} -declare module 'eslint/lib/api.js' { - declare module.exports: $Exports<'eslint/lib/api'>; -} -declare module 'eslint/lib/ast-utils.js' { - declare module.exports: $Exports<'eslint/lib/ast-utils'>; -} -declare module 'eslint/lib/cli-engine.js' { - declare module.exports: $Exports<'eslint/lib/cli-engine'>; -} -declare module 'eslint/lib/cli.js' { - declare module.exports: $Exports<'eslint/lib/cli'>; -} -declare module 'eslint/lib/code-path-analysis/code-path-analyzer.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-analyzer'>; -} -declare module 'eslint/lib/code-path-analysis/code-path-segment.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-segment'>; -} -declare module 'eslint/lib/code-path-analysis/code-path-state.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path-state'>; -} -declare module 'eslint/lib/code-path-analysis/code-path.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/code-path'>; -} -declare module 'eslint/lib/code-path-analysis/debug-helpers.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/debug-helpers'>; -} -declare module 'eslint/lib/code-path-analysis/fork-context.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/fork-context'>; -} -declare module 'eslint/lib/code-path-analysis/id-generator.js' { - declare module.exports: $Exports<'eslint/lib/code-path-analysis/id-generator'>; -} -declare module 'eslint/lib/config.js' { - declare module.exports: $Exports<'eslint/lib/config'>; -} -declare module 'eslint/lib/config/autoconfig.js' { - declare module.exports: $Exports<'eslint/lib/config/autoconfig'>; -} -declare module 'eslint/lib/config/config-file.js' { - declare module.exports: $Exports<'eslint/lib/config/config-file'>; -} -declare module 'eslint/lib/config/config-initializer.js' { - declare module.exports: $Exports<'eslint/lib/config/config-initializer'>; -} -declare module 'eslint/lib/config/config-ops.js' { - declare module.exports: $Exports<'eslint/lib/config/config-ops'>; -} -declare module 'eslint/lib/config/config-rule.js' { - declare module.exports: $Exports<'eslint/lib/config/config-rule'>; -} -declare module 'eslint/lib/config/config-validator.js' { - declare module.exports: $Exports<'eslint/lib/config/config-validator'>; -} -declare module 'eslint/lib/config/environments.js' { - declare module.exports: $Exports<'eslint/lib/config/environments'>; -} -declare module 'eslint/lib/config/plugins.js' { - declare module.exports: $Exports<'eslint/lib/config/plugins'>; -} -declare module 'eslint/lib/file-finder.js' { - declare module.exports: $Exports<'eslint/lib/file-finder'>; -} -declare module 'eslint/lib/formatters/checkstyle.js' { - declare module.exports: $Exports<'eslint/lib/formatters/checkstyle'>; -} -declare module 'eslint/lib/formatters/codeframe.js' { - declare module.exports: $Exports<'eslint/lib/formatters/codeframe'>; -} -declare module 'eslint/lib/formatters/compact.js' { - declare module.exports: $Exports<'eslint/lib/formatters/compact'>; -} -declare module 'eslint/lib/formatters/html.js' { - declare module.exports: $Exports<'eslint/lib/formatters/html'>; -} -declare module 'eslint/lib/formatters/jslint-xml.js' { - declare module.exports: $Exports<'eslint/lib/formatters/jslint-xml'>; -} -declare module 'eslint/lib/formatters/json.js' { - declare module.exports: $Exports<'eslint/lib/formatters/json'>; -} -declare module 'eslint/lib/formatters/junit.js' { - declare module.exports: $Exports<'eslint/lib/formatters/junit'>; -} -declare module 'eslint/lib/formatters/stylish.js' { - declare module.exports: $Exports<'eslint/lib/formatters/stylish'>; -} -declare module 'eslint/lib/formatters/table.js' { - declare module.exports: $Exports<'eslint/lib/formatters/table'>; -} -declare module 'eslint/lib/formatters/tap.js' { - declare module.exports: $Exports<'eslint/lib/formatters/tap'>; -} -declare module 'eslint/lib/formatters/unix.js' { - declare module.exports: $Exports<'eslint/lib/formatters/unix'>; -} -declare module 'eslint/lib/formatters/visualstudio.js' { - declare module.exports: $Exports<'eslint/lib/formatters/visualstudio'>; -} -declare module 'eslint/lib/ignored-paths.js' { - declare module.exports: $Exports<'eslint/lib/ignored-paths'>; -} -declare module 'eslint/lib/internal-rules/internal-consistent-docs-description.js' { - declare module.exports: $Exports<'eslint/lib/internal-rules/internal-consistent-docs-description'>; -} -declare module 'eslint/lib/internal-rules/internal-no-invalid-meta.js' { - declare module.exports: $Exports<'eslint/lib/internal-rules/internal-no-invalid-meta'>; -} -declare module 'eslint/lib/linter.js' { - declare module.exports: $Exports<'eslint/lib/linter'>; -} -declare module 'eslint/lib/load-rules.js' { - declare module.exports: $Exports<'eslint/lib/load-rules'>; -} -declare module 'eslint/lib/logging.js' { - declare module.exports: $Exports<'eslint/lib/logging'>; -} -declare module 'eslint/lib/options.js' { - declare module.exports: $Exports<'eslint/lib/options'>; -} -declare module 'eslint/lib/rule-context.js' { - declare module.exports: $Exports<'eslint/lib/rule-context'>; -} -declare module 'eslint/lib/rules.js' { - declare module.exports: $Exports<'eslint/lib/rules'>; -} -declare module 'eslint/lib/rules/accessor-pairs.js' { - declare module.exports: $Exports<'eslint/lib/rules/accessor-pairs'>; -} -declare module 'eslint/lib/rules/array-bracket-newline.js' { - declare module.exports: $Exports<'eslint/lib/rules/array-bracket-newline'>; -} -declare module 'eslint/lib/rules/array-bracket-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/array-bracket-spacing'>; -} -declare module 'eslint/lib/rules/array-callback-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/array-callback-return'>; -} -declare module 'eslint/lib/rules/array-element-newline.js' { - declare module.exports: $Exports<'eslint/lib/rules/array-element-newline'>; -} -declare module 'eslint/lib/rules/arrow-body-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/arrow-body-style'>; -} -declare module 'eslint/lib/rules/arrow-parens.js' { - declare module.exports: $Exports<'eslint/lib/rules/arrow-parens'>; -} -declare module 'eslint/lib/rules/arrow-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/arrow-spacing'>; -} -declare module 'eslint/lib/rules/block-scoped-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/block-scoped-var'>; -} -declare module 'eslint/lib/rules/block-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/block-spacing'>; -} -declare module 'eslint/lib/rules/brace-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/brace-style'>; -} -declare module 'eslint/lib/rules/callback-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/callback-return'>; -} -declare module 'eslint/lib/rules/camelcase.js' { - declare module.exports: $Exports<'eslint/lib/rules/camelcase'>; -} -declare module 'eslint/lib/rules/capitalized-comments.js' { - declare module.exports: $Exports<'eslint/lib/rules/capitalized-comments'>; -} -declare module 'eslint/lib/rules/class-methods-use-this.js' { - declare module.exports: $Exports<'eslint/lib/rules/class-methods-use-this'>; -} -declare module 'eslint/lib/rules/comma-dangle.js' { - declare module.exports: $Exports<'eslint/lib/rules/comma-dangle'>; -} -declare module 'eslint/lib/rules/comma-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/comma-spacing'>; -} -declare module 'eslint/lib/rules/comma-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/comma-style'>; -} -declare module 'eslint/lib/rules/complexity.js' { - declare module.exports: $Exports<'eslint/lib/rules/complexity'>; -} -declare module 'eslint/lib/rules/computed-property-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/computed-property-spacing'>; -} -declare module 'eslint/lib/rules/consistent-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/consistent-return'>; -} -declare module 'eslint/lib/rules/consistent-this.js' { - declare module.exports: $Exports<'eslint/lib/rules/consistent-this'>; -} -declare module 'eslint/lib/rules/constructor-super.js' { - declare module.exports: $Exports<'eslint/lib/rules/constructor-super'>; -} -declare module 'eslint/lib/rules/curly.js' { - declare module.exports: $Exports<'eslint/lib/rules/curly'>; -} -declare module 'eslint/lib/rules/default-case.js' { - declare module.exports: $Exports<'eslint/lib/rules/default-case'>; -} -declare module 'eslint/lib/rules/dot-location.js' { - declare module.exports: $Exports<'eslint/lib/rules/dot-location'>; -} -declare module 'eslint/lib/rules/dot-notation.js' { - declare module.exports: $Exports<'eslint/lib/rules/dot-notation'>; -} -declare module 'eslint/lib/rules/eol-last.js' { - declare module.exports: $Exports<'eslint/lib/rules/eol-last'>; -} -declare module 'eslint/lib/rules/eqeqeq.js' { - declare module.exports: $Exports<'eslint/lib/rules/eqeqeq'>; -} -declare module 'eslint/lib/rules/for-direction.js' { - declare module.exports: $Exports<'eslint/lib/rules/for-direction'>; -} -declare module 'eslint/lib/rules/func-call-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/func-call-spacing'>; -} -declare module 'eslint/lib/rules/func-name-matching.js' { - declare module.exports: $Exports<'eslint/lib/rules/func-name-matching'>; -} -declare module 'eslint/lib/rules/func-names.js' { - declare module.exports: $Exports<'eslint/lib/rules/func-names'>; -} -declare module 'eslint/lib/rules/func-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/func-style'>; -} -declare module 'eslint/lib/rules/generator-star-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/generator-star-spacing'>; -} -declare module 'eslint/lib/rules/global-require.js' { - declare module.exports: $Exports<'eslint/lib/rules/global-require'>; -} -declare module 'eslint/lib/rules/guard-for-in.js' { - declare module.exports: $Exports<'eslint/lib/rules/guard-for-in'>; -} -declare module 'eslint/lib/rules/handle-callback-err.js' { - declare module.exports: $Exports<'eslint/lib/rules/handle-callback-err'>; -} -declare module 'eslint/lib/rules/id-blacklist.js' { - declare module.exports: $Exports<'eslint/lib/rules/id-blacklist'>; -} -declare module 'eslint/lib/rules/id-length.js' { - declare module.exports: $Exports<'eslint/lib/rules/id-length'>; -} -declare module 'eslint/lib/rules/id-match.js' { - declare module.exports: $Exports<'eslint/lib/rules/id-match'>; -} -declare module 'eslint/lib/rules/indent-legacy.js' { - declare module.exports: $Exports<'eslint/lib/rules/indent-legacy'>; -} -declare module 'eslint/lib/rules/indent.js' { - declare module.exports: $Exports<'eslint/lib/rules/indent'>; -} -declare module 'eslint/lib/rules/init-declarations.js' { - declare module.exports: $Exports<'eslint/lib/rules/init-declarations'>; -} -declare module 'eslint/lib/rules/jsx-quotes.js' { - declare module.exports: $Exports<'eslint/lib/rules/jsx-quotes'>; -} -declare module 'eslint/lib/rules/key-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/key-spacing'>; -} -declare module 'eslint/lib/rules/keyword-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/keyword-spacing'>; -} -declare module 'eslint/lib/rules/line-comment-position.js' { - declare module.exports: $Exports<'eslint/lib/rules/line-comment-position'>; -} -declare module 'eslint/lib/rules/linebreak-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/linebreak-style'>; -} -declare module 'eslint/lib/rules/lines-around-comment.js' { - declare module.exports: $Exports<'eslint/lib/rules/lines-around-comment'>; -} -declare module 'eslint/lib/rules/lines-around-directive.js' { - declare module.exports: $Exports<'eslint/lib/rules/lines-around-directive'>; -} -declare module 'eslint/lib/rules/max-depth.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-depth'>; -} -declare module 'eslint/lib/rules/max-len.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-len'>; -} -declare module 'eslint/lib/rules/max-lines.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-lines'>; -} -declare module 'eslint/lib/rules/max-nested-callbacks.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-nested-callbacks'>; -} -declare module 'eslint/lib/rules/max-params.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-params'>; -} -declare module 'eslint/lib/rules/max-statements-per-line.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-statements-per-line'>; -} -declare module 'eslint/lib/rules/max-statements.js' { - declare module.exports: $Exports<'eslint/lib/rules/max-statements'>; -} -declare module 'eslint/lib/rules/multiline-ternary.js' { - declare module.exports: $Exports<'eslint/lib/rules/multiline-ternary'>; -} -declare module 'eslint/lib/rules/new-cap.js' { - declare module.exports: $Exports<'eslint/lib/rules/new-cap'>; -} -declare module 'eslint/lib/rules/new-parens.js' { - declare module.exports: $Exports<'eslint/lib/rules/new-parens'>; -} -declare module 'eslint/lib/rules/newline-after-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/newline-after-var'>; -} -declare module 'eslint/lib/rules/newline-before-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/newline-before-return'>; -} -declare module 'eslint/lib/rules/newline-per-chained-call.js' { - declare module.exports: $Exports<'eslint/lib/rules/newline-per-chained-call'>; -} -declare module 'eslint/lib/rules/no-alert.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-alert'>; -} -declare module 'eslint/lib/rules/no-array-constructor.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-array-constructor'>; -} -declare module 'eslint/lib/rules/no-await-in-loop.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-await-in-loop'>; -} -declare module 'eslint/lib/rules/no-bitwise.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-bitwise'>; -} -declare module 'eslint/lib/rules/no-buffer-constructor.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-buffer-constructor'>; -} -declare module 'eslint/lib/rules/no-caller.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-caller'>; -} -declare module 'eslint/lib/rules/no-case-declarations.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-case-declarations'>; -} -declare module 'eslint/lib/rules/no-catch-shadow.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-catch-shadow'>; -} -declare module 'eslint/lib/rules/no-class-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-class-assign'>; -} -declare module 'eslint/lib/rules/no-compare-neg-zero.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-compare-neg-zero'>; -} -declare module 'eslint/lib/rules/no-cond-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-cond-assign'>; -} -declare module 'eslint/lib/rules/no-confusing-arrow.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-confusing-arrow'>; -} -declare module 'eslint/lib/rules/no-console.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-console'>; -} -declare module 'eslint/lib/rules/no-const-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-const-assign'>; -} -declare module 'eslint/lib/rules/no-constant-condition.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-constant-condition'>; -} -declare module 'eslint/lib/rules/no-continue.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-continue'>; -} -declare module 'eslint/lib/rules/no-control-regex.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-control-regex'>; -} -declare module 'eslint/lib/rules/no-debugger.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-debugger'>; -} -declare module 'eslint/lib/rules/no-delete-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-delete-var'>; -} -declare module 'eslint/lib/rules/no-div-regex.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-div-regex'>; -} -declare module 'eslint/lib/rules/no-dupe-args.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-dupe-args'>; -} -declare module 'eslint/lib/rules/no-dupe-class-members.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-dupe-class-members'>; -} -declare module 'eslint/lib/rules/no-dupe-keys.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-dupe-keys'>; -} -declare module 'eslint/lib/rules/no-duplicate-case.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-duplicate-case'>; -} -declare module 'eslint/lib/rules/no-duplicate-imports.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-duplicate-imports'>; -} -declare module 'eslint/lib/rules/no-else-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-else-return'>; -} -declare module 'eslint/lib/rules/no-empty-character-class.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-empty-character-class'>; -} -declare module 'eslint/lib/rules/no-empty-function.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-empty-function'>; -} -declare module 'eslint/lib/rules/no-empty-pattern.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-empty-pattern'>; -} -declare module 'eslint/lib/rules/no-empty.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-empty'>; -} -declare module 'eslint/lib/rules/no-eq-null.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-eq-null'>; -} -declare module 'eslint/lib/rules/no-eval.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-eval'>; -} -declare module 'eslint/lib/rules/no-ex-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-ex-assign'>; -} -declare module 'eslint/lib/rules/no-extend-native.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extend-native'>; -} -declare module 'eslint/lib/rules/no-extra-bind.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extra-bind'>; -} -declare module 'eslint/lib/rules/no-extra-boolean-cast.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extra-boolean-cast'>; -} -declare module 'eslint/lib/rules/no-extra-label.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extra-label'>; -} -declare module 'eslint/lib/rules/no-extra-parens.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extra-parens'>; -} -declare module 'eslint/lib/rules/no-extra-semi.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-extra-semi'>; -} -declare module 'eslint/lib/rules/no-fallthrough.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-fallthrough'>; -} -declare module 'eslint/lib/rules/no-floating-decimal.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-floating-decimal'>; -} -declare module 'eslint/lib/rules/no-func-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-func-assign'>; -} -declare module 'eslint/lib/rules/no-global-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-global-assign'>; -} -declare module 'eslint/lib/rules/no-implicit-coercion.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-implicit-coercion'>; -} -declare module 'eslint/lib/rules/no-implicit-globals.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-implicit-globals'>; -} -declare module 'eslint/lib/rules/no-implied-eval.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-implied-eval'>; -} -declare module 'eslint/lib/rules/no-inline-comments.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-inline-comments'>; -} -declare module 'eslint/lib/rules/no-inner-declarations.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-inner-declarations'>; -} -declare module 'eslint/lib/rules/no-invalid-regexp.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-invalid-regexp'>; -} -declare module 'eslint/lib/rules/no-invalid-this.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-invalid-this'>; -} -declare module 'eslint/lib/rules/no-irregular-whitespace.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-irregular-whitespace'>; -} -declare module 'eslint/lib/rules/no-iterator.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-iterator'>; -} -declare module 'eslint/lib/rules/no-label-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-label-var'>; -} -declare module 'eslint/lib/rules/no-labels.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-labels'>; -} -declare module 'eslint/lib/rules/no-lone-blocks.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-lone-blocks'>; -} -declare module 'eslint/lib/rules/no-lonely-if.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-lonely-if'>; -} -declare module 'eslint/lib/rules/no-loop-func.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-loop-func'>; -} -declare module 'eslint/lib/rules/no-magic-numbers.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-magic-numbers'>; -} -declare module 'eslint/lib/rules/no-mixed-operators.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-mixed-operators'>; -} -declare module 'eslint/lib/rules/no-mixed-requires.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-mixed-requires'>; -} -declare module 'eslint/lib/rules/no-mixed-spaces-and-tabs.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-mixed-spaces-and-tabs'>; -} -declare module 'eslint/lib/rules/no-multi-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-multi-assign'>; -} -declare module 'eslint/lib/rules/no-multi-spaces.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-multi-spaces'>; -} -declare module 'eslint/lib/rules/no-multi-str.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-multi-str'>; -} -declare module 'eslint/lib/rules/no-multiple-empty-lines.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-multiple-empty-lines'>; -} -declare module 'eslint/lib/rules/no-native-reassign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-native-reassign'>; -} -declare module 'eslint/lib/rules/no-negated-condition.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-negated-condition'>; -} -declare module 'eslint/lib/rules/no-negated-in-lhs.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-negated-in-lhs'>; -} -declare module 'eslint/lib/rules/no-nested-ternary.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-nested-ternary'>; -} -declare module 'eslint/lib/rules/no-new-func.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new-func'>; -} -declare module 'eslint/lib/rules/no-new-object.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new-object'>; -} -declare module 'eslint/lib/rules/no-new-require.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new-require'>; -} -declare module 'eslint/lib/rules/no-new-symbol.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new-symbol'>; -} -declare module 'eslint/lib/rules/no-new-wrappers.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new-wrappers'>; -} -declare module 'eslint/lib/rules/no-new.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-new'>; -} -declare module 'eslint/lib/rules/no-obj-calls.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-obj-calls'>; -} -declare module 'eslint/lib/rules/no-octal-escape.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-octal-escape'>; -} -declare module 'eslint/lib/rules/no-octal.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-octal'>; -} -declare module 'eslint/lib/rules/no-param-reassign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-param-reassign'>; -} -declare module 'eslint/lib/rules/no-path-concat.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-path-concat'>; -} -declare module 'eslint/lib/rules/no-plusplus.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-plusplus'>; -} -declare module 'eslint/lib/rules/no-process-env.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-process-env'>; -} -declare module 'eslint/lib/rules/no-process-exit.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-process-exit'>; -} -declare module 'eslint/lib/rules/no-proto.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-proto'>; -} -declare module 'eslint/lib/rules/no-prototype-builtins.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-prototype-builtins'>; -} -declare module 'eslint/lib/rules/no-redeclare.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-redeclare'>; -} -declare module 'eslint/lib/rules/no-regex-spaces.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-regex-spaces'>; -} -declare module 'eslint/lib/rules/no-restricted-globals.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-restricted-globals'>; -} -declare module 'eslint/lib/rules/no-restricted-imports.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-restricted-imports'>; -} -declare module 'eslint/lib/rules/no-restricted-modules.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-restricted-modules'>; -} -declare module 'eslint/lib/rules/no-restricted-properties.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-restricted-properties'>; -} -declare module 'eslint/lib/rules/no-restricted-syntax.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-restricted-syntax'>; -} -declare module 'eslint/lib/rules/no-return-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-return-assign'>; -} -declare module 'eslint/lib/rules/no-return-await.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-return-await'>; -} -declare module 'eslint/lib/rules/no-script-url.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-script-url'>; -} -declare module 'eslint/lib/rules/no-self-assign.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-self-assign'>; -} -declare module 'eslint/lib/rules/no-self-compare.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-self-compare'>; -} -declare module 'eslint/lib/rules/no-sequences.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-sequences'>; -} -declare module 'eslint/lib/rules/no-shadow-restricted-names.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-shadow-restricted-names'>; -} -declare module 'eslint/lib/rules/no-shadow.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-shadow'>; -} -declare module 'eslint/lib/rules/no-spaced-func.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-spaced-func'>; -} -declare module 'eslint/lib/rules/no-sparse-arrays.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-sparse-arrays'>; -} -declare module 'eslint/lib/rules/no-sync.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-sync'>; -} -declare module 'eslint/lib/rules/no-tabs.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-tabs'>; -} -declare module 'eslint/lib/rules/no-template-curly-in-string.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-template-curly-in-string'>; -} -declare module 'eslint/lib/rules/no-ternary.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-ternary'>; -} -declare module 'eslint/lib/rules/no-this-before-super.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-this-before-super'>; -} -declare module 'eslint/lib/rules/no-throw-literal.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-throw-literal'>; -} -declare module 'eslint/lib/rules/no-trailing-spaces.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-trailing-spaces'>; -} -declare module 'eslint/lib/rules/no-undef-init.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-undef-init'>; -} -declare module 'eslint/lib/rules/no-undef.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-undef'>; -} -declare module 'eslint/lib/rules/no-undefined.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-undefined'>; -} -declare module 'eslint/lib/rules/no-underscore-dangle.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-underscore-dangle'>; -} -declare module 'eslint/lib/rules/no-unexpected-multiline.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unexpected-multiline'>; -} -declare module 'eslint/lib/rules/no-unmodified-loop-condition.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unmodified-loop-condition'>; -} -declare module 'eslint/lib/rules/no-unneeded-ternary.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unneeded-ternary'>; -} -declare module 'eslint/lib/rules/no-unreachable.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unreachable'>; -} -declare module 'eslint/lib/rules/no-unsafe-finally.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unsafe-finally'>; -} -declare module 'eslint/lib/rules/no-unsafe-negation.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unsafe-negation'>; -} -declare module 'eslint/lib/rules/no-unused-expressions.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unused-expressions'>; -} -declare module 'eslint/lib/rules/no-unused-labels.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unused-labels'>; -} -declare module 'eslint/lib/rules/no-unused-vars.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-unused-vars'>; -} -declare module 'eslint/lib/rules/no-use-before-define.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-use-before-define'>; -} -declare module 'eslint/lib/rules/no-useless-call.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-call'>; -} -declare module 'eslint/lib/rules/no-useless-computed-key.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-computed-key'>; -} -declare module 'eslint/lib/rules/no-useless-concat.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-concat'>; -} -declare module 'eslint/lib/rules/no-useless-constructor.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-constructor'>; -} -declare module 'eslint/lib/rules/no-useless-escape.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-escape'>; -} -declare module 'eslint/lib/rules/no-useless-rename.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-rename'>; -} -declare module 'eslint/lib/rules/no-useless-return.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-useless-return'>; -} -declare module 'eslint/lib/rules/no-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-var'>; -} -declare module 'eslint/lib/rules/no-void.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-void'>; -} -declare module 'eslint/lib/rules/no-warning-comments.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-warning-comments'>; -} -declare module 'eslint/lib/rules/no-whitespace-before-property.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-whitespace-before-property'>; -} -declare module 'eslint/lib/rules/no-with.js' { - declare module.exports: $Exports<'eslint/lib/rules/no-with'>; -} -declare module 'eslint/lib/rules/nonblock-statement-body-position.js' { - declare module.exports: $Exports<'eslint/lib/rules/nonblock-statement-body-position'>; -} -declare module 'eslint/lib/rules/object-curly-newline.js' { - declare module.exports: $Exports<'eslint/lib/rules/object-curly-newline'>; -} -declare module 'eslint/lib/rules/object-curly-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/object-curly-spacing'>; -} -declare module 'eslint/lib/rules/object-property-newline.js' { - declare module.exports: $Exports<'eslint/lib/rules/object-property-newline'>; -} -declare module 'eslint/lib/rules/object-shorthand.js' { - declare module.exports: $Exports<'eslint/lib/rules/object-shorthand'>; -} -declare module 'eslint/lib/rules/one-var-declaration-per-line.js' { - declare module.exports: $Exports<'eslint/lib/rules/one-var-declaration-per-line'>; -} -declare module 'eslint/lib/rules/one-var.js' { - declare module.exports: $Exports<'eslint/lib/rules/one-var'>; -} -declare module 'eslint/lib/rules/operator-assignment.js' { - declare module.exports: $Exports<'eslint/lib/rules/operator-assignment'>; -} -declare module 'eslint/lib/rules/operator-linebreak.js' { - declare module.exports: $Exports<'eslint/lib/rules/operator-linebreak'>; -} -declare module 'eslint/lib/rules/padded-blocks.js' { - declare module.exports: $Exports<'eslint/lib/rules/padded-blocks'>; -} -declare module 'eslint/lib/rules/padding-line-between-statements.js' { - declare module.exports: $Exports<'eslint/lib/rules/padding-line-between-statements'>; -} -declare module 'eslint/lib/rules/prefer-arrow-callback.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-arrow-callback'>; -} -declare module 'eslint/lib/rules/prefer-const.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-const'>; -} -declare module 'eslint/lib/rules/prefer-destructuring.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-destructuring'>; -} -declare module 'eslint/lib/rules/prefer-numeric-literals.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-numeric-literals'>; -} -declare module 'eslint/lib/rules/prefer-promise-reject-errors.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-promise-reject-errors'>; -} -declare module 'eslint/lib/rules/prefer-reflect.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-reflect'>; -} -declare module 'eslint/lib/rules/prefer-rest-params.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-rest-params'>; -} -declare module 'eslint/lib/rules/prefer-spread.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-spread'>; -} -declare module 'eslint/lib/rules/prefer-template.js' { - declare module.exports: $Exports<'eslint/lib/rules/prefer-template'>; -} -declare module 'eslint/lib/rules/quote-props.js' { - declare module.exports: $Exports<'eslint/lib/rules/quote-props'>; -} -declare module 'eslint/lib/rules/quotes.js' { - declare module.exports: $Exports<'eslint/lib/rules/quotes'>; -} -declare module 'eslint/lib/rules/radix.js' { - declare module.exports: $Exports<'eslint/lib/rules/radix'>; -} -declare module 'eslint/lib/rules/require-await.js' { - declare module.exports: $Exports<'eslint/lib/rules/require-await'>; -} -declare module 'eslint/lib/rules/require-jsdoc.js' { - declare module.exports: $Exports<'eslint/lib/rules/require-jsdoc'>; -} -declare module 'eslint/lib/rules/require-yield.js' { - declare module.exports: $Exports<'eslint/lib/rules/require-yield'>; -} -declare module 'eslint/lib/rules/rest-spread-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/rest-spread-spacing'>; -} -declare module 'eslint/lib/rules/semi-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/semi-spacing'>; -} -declare module 'eslint/lib/rules/semi-style.js' { - declare module.exports: $Exports<'eslint/lib/rules/semi-style'>; -} -declare module 'eslint/lib/rules/semi.js' { - declare module.exports: $Exports<'eslint/lib/rules/semi'>; -} -declare module 'eslint/lib/rules/sort-imports.js' { - declare module.exports: $Exports<'eslint/lib/rules/sort-imports'>; -} -declare module 'eslint/lib/rules/sort-keys.js' { - declare module.exports: $Exports<'eslint/lib/rules/sort-keys'>; -} -declare module 'eslint/lib/rules/sort-vars.js' { - declare module.exports: $Exports<'eslint/lib/rules/sort-vars'>; -} -declare module 'eslint/lib/rules/space-before-blocks.js' { - declare module.exports: $Exports<'eslint/lib/rules/space-before-blocks'>; -} -declare module 'eslint/lib/rules/space-before-function-paren.js' { - declare module.exports: $Exports<'eslint/lib/rules/space-before-function-paren'>; -} -declare module 'eslint/lib/rules/space-in-parens.js' { - declare module.exports: $Exports<'eslint/lib/rules/space-in-parens'>; -} -declare module 'eslint/lib/rules/space-infix-ops.js' { - declare module.exports: $Exports<'eslint/lib/rules/space-infix-ops'>; -} -declare module 'eslint/lib/rules/space-unary-ops.js' { - declare module.exports: $Exports<'eslint/lib/rules/space-unary-ops'>; -} -declare module 'eslint/lib/rules/spaced-comment.js' { - declare module.exports: $Exports<'eslint/lib/rules/spaced-comment'>; -} -declare module 'eslint/lib/rules/strict.js' { - declare module.exports: $Exports<'eslint/lib/rules/strict'>; -} -declare module 'eslint/lib/rules/switch-colon-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/switch-colon-spacing'>; -} -declare module 'eslint/lib/rules/symbol-description.js' { - declare module.exports: $Exports<'eslint/lib/rules/symbol-description'>; -} -declare module 'eslint/lib/rules/template-curly-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/template-curly-spacing'>; -} -declare module 'eslint/lib/rules/template-tag-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/template-tag-spacing'>; -} -declare module 'eslint/lib/rules/unicode-bom.js' { - declare module.exports: $Exports<'eslint/lib/rules/unicode-bom'>; -} -declare module 'eslint/lib/rules/use-isnan.js' { - declare module.exports: $Exports<'eslint/lib/rules/use-isnan'>; -} -declare module 'eslint/lib/rules/valid-jsdoc.js' { - declare module.exports: $Exports<'eslint/lib/rules/valid-jsdoc'>; -} -declare module 'eslint/lib/rules/valid-typeof.js' { - declare module.exports: $Exports<'eslint/lib/rules/valid-typeof'>; -} -declare module 'eslint/lib/rules/vars-on-top.js' { - declare module.exports: $Exports<'eslint/lib/rules/vars-on-top'>; -} -declare module 'eslint/lib/rules/wrap-iife.js' { - declare module.exports: $Exports<'eslint/lib/rules/wrap-iife'>; -} -declare module 'eslint/lib/rules/wrap-regex.js' { - declare module.exports: $Exports<'eslint/lib/rules/wrap-regex'>; -} -declare module 'eslint/lib/rules/yield-star-spacing.js' { - declare module.exports: $Exports<'eslint/lib/rules/yield-star-spacing'>; -} -declare module 'eslint/lib/rules/yoda.js' { - declare module.exports: $Exports<'eslint/lib/rules/yoda'>; -} -declare module 'eslint/lib/testers/event-generator-tester.js' { - declare module.exports: $Exports<'eslint/lib/testers/event-generator-tester'>; -} -declare module 'eslint/lib/testers/rule-tester.js' { - declare module.exports: $Exports<'eslint/lib/testers/rule-tester'>; -} -declare module 'eslint/lib/timing.js' { - declare module.exports: $Exports<'eslint/lib/timing'>; -} -declare module 'eslint/lib/token-store/backward-token-comment-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/backward-token-comment-cursor'>; -} -declare module 'eslint/lib/token-store/backward-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/backward-token-cursor'>; -} -declare module 'eslint/lib/token-store/cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/cursor'>; -} -declare module 'eslint/lib/token-store/cursors.js' { - declare module.exports: $Exports<'eslint/lib/token-store/cursors'>; -} -declare module 'eslint/lib/token-store/decorative-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/decorative-cursor'>; -} -declare module 'eslint/lib/token-store/filter-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/filter-cursor'>; -} -declare module 'eslint/lib/token-store/forward-token-comment-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/forward-token-comment-cursor'>; -} -declare module 'eslint/lib/token-store/forward-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/forward-token-cursor'>; -} -declare module 'eslint/lib/token-store/index.js' { - declare module.exports: $Exports<'eslint/lib/token-store/index'>; -} -declare module 'eslint/lib/token-store/limit-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/limit-cursor'>; -} -declare module 'eslint/lib/token-store/padded-token-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/padded-token-cursor'>; -} -declare module 'eslint/lib/token-store/skip-cursor.js' { - declare module.exports: $Exports<'eslint/lib/token-store/skip-cursor'>; -} -declare module 'eslint/lib/token-store/utils.js' { - declare module.exports: $Exports<'eslint/lib/token-store/utils'>; -} -declare module 'eslint/lib/util/fix-tracker.js' { - declare module.exports: $Exports<'eslint/lib/util/fix-tracker'>; -} -declare module 'eslint/lib/util/glob-util.js' { - declare module.exports: $Exports<'eslint/lib/util/glob-util'>; -} -declare module 'eslint/lib/util/glob.js' { - declare module.exports: $Exports<'eslint/lib/util/glob'>; -} -declare module 'eslint/lib/util/hash.js' { - declare module.exports: $Exports<'eslint/lib/util/hash'>; -} -declare module 'eslint/lib/util/keywords.js' { - declare module.exports: $Exports<'eslint/lib/util/keywords'>; -} -declare module 'eslint/lib/util/module-resolver.js' { - declare module.exports: $Exports<'eslint/lib/util/module-resolver'>; -} -declare module 'eslint/lib/util/node-event-generator.js' { - declare module.exports: $Exports<'eslint/lib/util/node-event-generator'>; -} -declare module 'eslint/lib/util/npm-util.js' { - declare module.exports: $Exports<'eslint/lib/util/npm-util'>; -} -declare module 'eslint/lib/util/path-util.js' { - declare module.exports: $Exports<'eslint/lib/util/path-util'>; -} -declare module 'eslint/lib/util/patterns/letters.js' { - declare module.exports: $Exports<'eslint/lib/util/patterns/letters'>; -} -declare module 'eslint/lib/util/rule-fixer.js' { - declare module.exports: $Exports<'eslint/lib/util/rule-fixer'>; -} -declare module 'eslint/lib/util/source-code-fixer.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code-fixer'>; -} -declare module 'eslint/lib/util/source-code-util.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code-util'>; -} -declare module 'eslint/lib/util/source-code.js' { - declare module.exports: $Exports<'eslint/lib/util/source-code'>; -} -declare module 'eslint/lib/util/traverser.js' { - declare module.exports: $Exports<'eslint/lib/util/traverser'>; -} -declare module 'eslint/lib/util/xml-escape.js' { - declare module.exports: $Exports<'eslint/lib/util/xml-escape'>; -} diff --git a/flow-typed/npm/flow-bin_v0.x.x.js b/flow-typed/npm/flow-bin_v0.x.x.js deleted file mode 100644 index c538e2086..000000000 --- a/flow-typed/npm/flow-bin_v0.x.x.js +++ /dev/null @@ -1,6 +0,0 @@ -// flow-typed signature: 6a5610678d4b01e13bbfbbc62bdaf583 -// flow-typed version: 3817bc6980/flow-bin_v0.x.x/flow_>=v0.25.x - -declare module "flow-bin" { - declare module.exports: string; -} diff --git a/flow-typed/npm/inquirer_v1.x.x.js b/flow-typed/npm/inquirer_v1.x.x.js deleted file mode 100644 index c2aebfdac..000000000 --- a/flow-typed/npm/inquirer_v1.x.x.js +++ /dev/null @@ -1,339 +0,0 @@ -/** - * Flowtype definitions for inquirer - * Generated by Flowgen from a Typescript Definition - * Flowgen v1.0.0 - * Author: [Joar Wilk](http://twitter.com/joarwilk) - * Repo: http://github.com/joarwilk/flowgen - */ - - // Edited, with original version from https://github.com/joarwilk/flow-typed/blob/2e0576cd5a1202ebaad056c681042612e4d3f02b/definitions/npm/inquirer_v1.x.x/flow_v0.35.x-/inquirer.js - -declare module 'inquirer' { - declare type inquirer$Prompts = { - [name: string]: inquirer$PromptModule - }; - - declare type inquirer$ChoiceType = string | objects$ChoiceOption | objects$Separator; - - declare type inquirer$Questions = inquirer$Question | inquirer$Question[]; - - declare interface inquirer$Inquirer { - restoreDefaultPrompts(): void, - - /** - * Expose helper functions on the top level for easiest usage by common users - * @param name - * @param prompt - */ - registerPrompt(name: string, prompt: inquirer$PromptModule): void, - - /** - * Create a new self-contained prompt module. - */ - createPromptModule(): inquirer$PromptModule, - - /** - * Public CLI helper interface - * @param questions Questions settings array - * @param cb Callback being passed the user answers - * @return - */ - prompt( - questions: inquirer$Questions, - cb: (answers: inquirer$Answers) => any): ui$Prompt, - prompt(questions: inquirer$Questions): Promise, - prompts: inquirer$Prompts, - Separator: objects$SeparatorStatic, - ui: { - BottomBar: ui$BottomBar, - Prompt: ui$Prompt - } - } - - declare interface inquirer$PromptModule { - (questions: inquirer$Questions, cb: (answers: inquirer$Answers) => any): ui$Prompt, - - /** - * Register a prompt type - * @param name Prompt type name - * @param prompt Prompt constructor - */ - registerPrompt(name: string, prompt: inquirer$PromptModule): ui$Prompt, - - /** - * Register the defaults provider prompts - */ - restoreDefaultPrompts(): void - } - - declare interface inquirer$Question { - - /** - * Type of the prompt. - * Possible values: -
      -
    • input
    • -
    • confirm
    • -
    • list
    • -
    • rawlist
    • -
    • password
    • -
    - * @defaults : 'input' - */ - type?: string, - - /** - * The name to use when storing the answer in the anwers hash. - */ - name?: string, - - /** - * The question to print. If defined as a function, - * the first parameter will be the current inquirer session answers. - */ - +message?: string | ((answers: inquirer$Answers) => string), - - /** - * Default value(s) to use if nothing is entered, or a function that returns the default value(s). - * If defined as a function, the first parameter will be the current inquirer session answers. - */ - +default?: any | ((answers: inquirer$Answers) => any), - - /** - * Choices array or a function returning a choices array. If defined as a function, - * the first parameter will be the current inquirer session answers. - Array values can be simple strings, or objects containing a name (to display) and a value properties - (to save in the answers hash). Values can also be a Separator. - */ - +choices?: inquirer$ChoiceType[] | ((answers: inquirer$Answers) => inquirer$ChoiceType[]), - - /** - * Receive the user input and should return true if the value is valid, and an error message (String) - * otherwise. If false is returned, a default error message is provided. - */ - validate?: (input: string) => boolean | string, - - /** - * Receive the user input and return the filtered value to be used inside the program. - * The value returned will be added to the Answers hash. - */ - filter?: (input: string) => string, - - /** - * Receive the current user answers hash and should return true or false depending on whether or - * not this question should be asked. The value can also be a simple boolean. - */ - +when?: boolean | ((answers: inquirer$Answers) => boolean), - paginated?: boolean - } - - - /** - * A key/value hash containing the client answers in each prompt. - */ - declare type inquirer$Answers = {| - +[key: string]: any - |} - - - /** - * Base interface class other can inherits from - */ - declare type ui$Prompt = { - new(promptModule: inquirer$Prompts): ui$Prompt, - - /** - * Once all prompt are over - */ - onCompletion(): void, - processQuestion(question: inquirer$Question): any, - fetchAnswer(question: inquirer$Question): any, - setDefaultType(question: inquirer$Question): any, - filterIfRunnable(question: inquirer$Question): any - } & ui$BaseUI - - - - /** - * Sticky bottom bar user interface - */ - declare type ui$BottomBar = { - new(opt?: ui$BottomBarOption): ui$BottomBar, - - /** - * Render the prompt to screen - * @return self - */ - render(): ui$BottomBar, - - /** - * Update the bottom bar content and rerender - * @param bottomBar Bottom bar content - * @return self - */ - updateBottomBar(bottomBar: string): ui$BottomBar, - - /** - * Rerender the prompt - * @return self - */ - writeLog(data: any): ui$BottomBar, - - /** - * Make sure line end on a line feed - * @param str Input string - * @return The input string with a final line feed - */ - enforceLF(str: string): string, - - /** - * Helper for writing message in Prompt - * @param message The message to be output - */ - // write(message: string): void, - // log: through.ThroughStream - } & ui$BaseUI - - - declare interface ui$BottomBarOption { - bottomBar?: string - } - - - /** - * Base interface class other can inherits from - */ - declare interface ui$BaseUI{ - new(opt: TOpt): void, - - /** - * Handle the ^C exit - * @return - */ - onForceClose(): void, - - /** - * Close the interface and cleanup listeners - */ - close(): void, - - /** - * Handle and propagate keypress events - */ - onKeypress(s: string, key: ui$Key): void - } - - declare interface ui$Key { - sequence: string, - name: string, - meta: boolean, - shift: boolean, - ctrl: boolean - } - - - /** - * Choice object - * Normalize input as choice object - * @constructor * - * @param Choice value. If an object is passed, it should contains - at least one of `value` or `name` property - */ - declare interface objects$Choice { - new(str: string): objects$Choice, - new(separator: objects$Separator): objects$Choice, - new(option: objects$ChoiceOption): objects$Choice - } - - declare interface objects$ChoiceOption { - name?: string, - value?: string, - type?: string, - extra?: any, - key?: string, - checked?: boolean, - disabled?: string | ((answers: inquirer$Answers) => any) - } - - - /** - * Choices collection - * Collection of multiple `choice` object - * @constructor * - * @param choices All `choice` to keep in the collection - */ - declare interface objects$Choices { - new( - choices: (string | objects$Separator | objects$ChoiceOption)[], - answers?: inquirer$Answers): objects$Choices, - choices: objects$Choice[], - realChoices: objects$Choice[], - length: number, - realLength: number, - - /** - * Get a valid choice from the collection - * @param selector The selected choice index - * @return Return the matched choice or undefined - */ - getChoice(selector: number): objects$Choice, - - /** - * Get a raw element from the collection - * @param selector The selected index value - * @return Return the matched choice or undefined - */ - get(selector: number): objects$Choice, - - /** - * Match the valid choices against a where clause - * @param whereClause Lodash `where` clause - * @return Matching choices or empty array - */ - where(whereClause: U): objects$Choice[], - - /** - * Pluck a particular key from the choices - * @param propertyName Property name to select - * @return Selected properties - */ - pluck(propertyName: string): any[], - forEach(application: (choice: objects$Choice) => T): T[] - } - - declare interface objects$SeparatorStatic { - - /** - * - * @param line Separation line content (facultative) - */ - new(line?: string): objects$Separator, - - /** - * Helper function returning false if object is a separator - * @param obj object to test against - * @return `false` if object is a separator - */ - exclude(obj: any): boolean - } - - - /** - * Separator object - * Used to space/separate choices group - * @constructor * - * @param Separation line content (facultative) - */ - declare interface objects$Separator { - type: string, - line: string, - - /** - * Stringify separator - * @return the separator display string - */ - toString(): string - } - declare var inquirer: inquirer$Inquirer; - declare module.exports: typeof inquirer -} \ No newline at end of file diff --git a/flow-typed/npm/jest_v22.x.x.js b/flow-typed/npm/jest_v22.x.x.js deleted file mode 100644 index f3b69c4a3..000000000 --- a/flow-typed/npm/jest_v22.x.x.js +++ /dev/null @@ -1,661 +0,0 @@ -// flow-typed signature: 069387a9f0aaed26ad0eb69da26f3e03 -// flow-typed version: 2c21d4538f/jest_v22.x.x/flow_>=v0.39.x - -type JestMockFn, TReturn> = { - (...args: TArguments): TReturn, - /** - * An object for introspecting mock calls - */ - mock: { - /** - * An array that represents all calls that have been made into this mock - * function. Each call is represented by an array of arguments that were - * passed during the call. - */ - calls: Array, - /** - * An array that contains all the object instances that have been - * instantiated from this mock function. - */ - instances: Array - }, - /** - * Resets all information stored in the mockFn.mock.calls and - * mockFn.mock.instances arrays. Often this is useful when you want to clean - * up a mock's usage data between two assertions. - */ - mockClear(): void, - /** - * Resets all information stored in the mock. This is useful when you want to - * completely restore a mock back to its initial state. - */ - mockReset(): void, - /** - * Removes the mock and restores the initial implementation. This is useful - * when you want to mock functions in certain test cases and restore the - * original implementation in others. Beware that mockFn.mockRestore only - * works when mock was created with jest.spyOn. Thus you have to take care of - * restoration yourself when manually assigning jest.fn(). - */ - mockRestore(): void, - /** - * Accepts a function that should be used as the implementation of the mock. - * The mock itself will still record all calls that go into and instances - * that come from itself -- the only difference is that the implementation - * will also be executed when the mock is called. - */ - mockImplementation( - fn: (...args: TArguments) => TReturn - ): JestMockFn, - /** - * Accepts a function that will be used as an implementation of the mock for - * one call to the mocked function. Can be chained so that multiple function - * calls produce different results. - */ - mockImplementationOnce( - fn: (...args: TArguments) => TReturn - ): JestMockFn, - /** - * Accepts a string to use in test result output in place of "jest.fn()" to - * indicate which mock function is being referenced. - */ - mockName(name: string): JestMockFn, - /** - * Just a simple sugar function for returning `this` - */ - mockReturnThis(): void, - /** - * Deprecated: use jest.fn(() => value) instead - */ - mockReturnValue(value: TReturn): JestMockFn, - /** - * Sugar for only returning a value once inside your mock - */ - mockReturnValueOnce(value: TReturn): JestMockFn -}; - -type JestAsymmetricEqualityType = { - /** - * A custom Jasmine equality tester - */ - asymmetricMatch(value: mixed): boolean -}; - -type JestCallsType = { - allArgs(): mixed, - all(): mixed, - any(): boolean, - count(): number, - first(): mixed, - mostRecent(): mixed, - reset(): void -}; - -type JestClockType = { - install(): void, - mockDate(date: Date): void, - tick(milliseconds?: number): void, - uninstall(): void -}; - -type JestMatcherResult = { - message?: string | (() => string), - pass: boolean -}; - -type JestMatcher = (actual: any, expected: any) => JestMatcherResult; - -type JestPromiseType = { - /** - * Use rejects to unwrap the reason of a rejected promise so any other - * matcher can be chained. If the promise is fulfilled the assertion fails. - */ - rejects: JestExpectType, - /** - * Use resolves to unwrap the value of a fulfilled promise so any other - * matcher can be chained. If the promise is rejected the assertion fails. - */ - resolves: JestExpectType -}; - -/** - * Jest allows functions and classes to be used as test names in test() and - * describe() - */ -type JestTestName = string | Function; - -/** - * Plugin: jest-enzyme - */ -type EnzymeMatchersType = { - toBeChecked(): void, - toBeDisabled(): void, - toBeEmpty(): void, - toBeEmptyRender(): void, - toBePresent(): void, - toContainReact(element: React$Element): void, - toExist(): void, - toHaveClassName(className: string): void, - toHaveHTML(html: string): void, - toHaveProp: ((propKey: string, propValue?: any) => void) & ((props: Object) => void), - toHaveRef(refName: string): void, - toHaveState: ((stateKey: string, stateValue?: any) => void) & ((state: Object) => void), - toHaveStyle: ((styleKey: string, styleValue?: any) => void) & ((style: Object) => void), - toHaveTagName(tagName: string): void, - toHaveText(text: string): void, - toIncludeText(text: string): void, - toHaveValue(value: any): void, - toMatchElement(element: React$Element): void, - toMatchSelector(selector: string): void -}; - -// DOM testing library extensions https://github.com/kentcdodds/dom-testing-library#custom-jest-matchers -type DomTestingLibraryType = { - toBeInTheDOM(): void, - toHaveTextContent(content: string): void, - toHaveAttribute(name: string, expectedValue?: string): void -}; - -type JestExpectType = { - not: JestExpectType & EnzymeMatchersType & DomTestingLibraryType, - /** - * If you have a mock function, you can use .lastCalledWith to test what - * arguments it was last called with. - */ - lastCalledWith(...args: Array): void, - /** - * toBe just checks that a value is what you expect. It uses === to check - * strict equality. - */ - toBe(value: any): void, - /** - * Use .toHaveBeenCalled to ensure that a mock function got called. - */ - toBeCalled(): void, - /** - * Use .toBeCalledWith to ensure that a mock function was called with - * specific arguments. - */ - toBeCalledWith(...args: Array): void, - /** - * Using exact equality with floating point numbers is a bad idea. Rounding - * means that intuitive things fail. - */ - toBeCloseTo(num: number, delta: any): void, - /** - * Use .toBeDefined to check that a variable is not undefined. - */ - toBeDefined(): void, - /** - * Use .toBeFalsy when you don't care what a value is, you just want to - * ensure a value is false in a boolean context. - */ - toBeFalsy(): void, - /** - * To compare floating point numbers, you can use toBeGreaterThan. - */ - toBeGreaterThan(number: number): void, - /** - * To compare floating point numbers, you can use toBeGreaterThanOrEqual. - */ - toBeGreaterThanOrEqual(number: number): void, - /** - * To compare floating point numbers, you can use toBeLessThan. - */ - toBeLessThan(number: number): void, - /** - * To compare floating point numbers, you can use toBeLessThanOrEqual. - */ - toBeLessThanOrEqual(number: number): void, - /** - * Use .toBeInstanceOf(Class) to check that an object is an instance of a - * class. - */ - toBeInstanceOf(cls: Class<*>): void, - /** - * .toBeNull() is the same as .toBe(null) but the error messages are a bit - * nicer. - */ - toBeNull(): void, - /** - * Use .toBeTruthy when you don't care what a value is, you just want to - * ensure a value is true in a boolean context. - */ - toBeTruthy(): void, - /** - * Use .toBeUndefined to check that a variable is undefined. - */ - toBeUndefined(): void, - /** - * Use .toContain when you want to check that an item is in a list. For - * testing the items in the list, this uses ===, a strict equality check. - */ - toContain(item: any): void, - /** - * Use .toContainEqual when you want to check that an item is in a list. For - * testing the items in the list, this matcher recursively checks the - * equality of all fields, rather than checking for object identity. - */ - toContainEqual(item: any): void, - /** - * Use .toEqual when you want to check that two objects have the same value. - * This matcher recursively checks the equality of all fields, rather than - * checking for object identity. - */ - toEqual(value: any): void, - /** - * Use .toHaveBeenCalled to ensure that a mock function got called. - */ - toHaveBeenCalled(): void, - /** - * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact - * number of times. - */ - toHaveBeenCalledTimes(number: number): void, - /** - * Use .toHaveBeenCalledWith to ensure that a mock function was called with - * specific arguments. - */ - toHaveBeenCalledWith(...args: Array): void, - /** - * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called - * with specific arguments. - */ - toHaveBeenLastCalledWith(...args: Array): void, - /** - * Check that an object has a .length property and it is set to a certain - * numeric value. - */ - toHaveLength(number: number): void, - /** - * - */ - toHaveProperty(propPath: string, value?: any): void, - /** - * Use .toMatch to check that a string matches a regular expression or string. - */ - toMatch(regexpOrString: RegExp | string): void, - /** - * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object. - */ - toMatchObject(object: Object | Array): void, - /** - * This ensures that a React component matches the most recent snapshot. - */ - toMatchSnapshot(name?: string): void, - /** - * Use .toThrow to test that a function throws when it is called. - * If you want to test that a specific error gets thrown, you can provide an - * argument to toThrow. The argument can be a string for the error message, - * a class for the error, or a regex that should match the error. - * - * Alias: .toThrowError - */ - toThrow(message?: string | Error | Class | RegExp): void, - toThrowError(message?: string | Error | Class | RegExp): void, - /** - * Use .toThrowErrorMatchingSnapshot to test that a function throws a error - * matching the most recent snapshot when it is called. - */ - toThrowErrorMatchingSnapshot(): void -}; - -type JestObjectType = { - /** - * Disables automatic mocking in the module loader. - * - * After this method is called, all `require()`s will return the real - * versions of each module (rather than a mocked version). - */ - disableAutomock(): JestObjectType, - /** - * An un-hoisted version of disableAutomock - */ - autoMockOff(): JestObjectType, - /** - * Enables automatic mocking in the module loader. - */ - enableAutomock(): JestObjectType, - /** - * An un-hoisted version of enableAutomock - */ - autoMockOn(): JestObjectType, - /** - * Clears the mock.calls and mock.instances properties of all mocks. - * Equivalent to calling .mockClear() on every mocked function. - */ - clearAllMocks(): JestObjectType, - /** - * Resets the state of all mocks. Equivalent to calling .mockReset() on every - * mocked function. - */ - resetAllMocks(): JestObjectType, - /** - * Restores all mocks back to their original value. - */ - restoreAllMocks(): JestObjectType, - /** - * Removes any pending timers from the timer system. - */ - clearAllTimers(): void, - /** - * The same as `mock` but not moved to the top of the expectation by - * babel-jest. - */ - doMock(moduleName: string, moduleFactory?: any): JestObjectType, - /** - * The same as `unmock` but not moved to the top of the expectation by - * babel-jest. - */ - dontMock(moduleName: string): JestObjectType, - /** - * Returns a new, unused mock function. Optionally takes a mock - * implementation. - */ - fn, TReturn>( - implementation?: (...args: TArguments) => TReturn - ): JestMockFn, - /** - * Determines if the given function is a mocked function. - */ - isMockFunction(fn: Function): boolean, - /** - * Given the name of a module, use the automatic mocking system to generate a - * mocked version of the module for you. - */ - genMockFromModule(moduleName: string): any, - /** - * Mocks a module with an auto-mocked version when it is being required. - * - * The second argument can be used to specify an explicit module factory that - * is being run instead of using Jest's automocking feature. - * - * The third argument can be used to create virtual mocks -- mocks of modules - * that don't exist anywhere in the system. - */ - mock( - moduleName: string, - moduleFactory?: any, - options?: Object - ): JestObjectType, - /** - * Returns the actual module instead of a mock, bypassing all checks on - * whether the module should receive a mock implementation or not. - */ - requireActual(moduleName: string): any, - /** - * Returns a mock module instead of the actual module, bypassing all checks - * on whether the module should be required normally or not. - */ - requireMock(moduleName: string): any, - /** - * Resets the module registry - the cache of all required modules. This is - * useful to isolate modules where local state might conflict between tests. - */ - resetModules(): JestObjectType, - /** - * Exhausts the micro-task queue (usually interfaced in node via - * process.nextTick). - */ - runAllTicks(): void, - /** - * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(), - * setInterval(), and setImmediate()). - */ - runAllTimers(): void, - /** - * Exhausts all tasks queued by setImmediate(). - */ - runAllImmediates(): void, - /** - * Executes only the macro task queue (i.e. all tasks queued by setTimeout() - * or setInterval() and setImmediate()). - */ - advanceTimersByTime(msToRun: number): void, - /** - * Executes only the macro task queue (i.e. all tasks queued by setTimeout() - * or setInterval() and setImmediate()). - * - * Renamed to `advanceTimersByTime`. - */ - runTimersToTime(msToRun: number): void, - /** - * Executes only the macro-tasks that are currently pending (i.e., only the - * tasks that have been queued by setTimeout() or setInterval() up to this - * point) - */ - runOnlyPendingTimers(): void, - /** - * Explicitly supplies the mock object that the module system should return - * for the specified module. Note: It is recommended to use jest.mock() - * instead. - */ - setMock(moduleName: string, moduleExports: any): JestObjectType, - /** - * Indicates that the module system should never return a mocked version of - * the specified module from require() (e.g. that it should always return the - * real module). - */ - unmock(moduleName: string): JestObjectType, - /** - * Instructs Jest to use fake versions of the standard timer functions - * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick, - * setImmediate and clearImmediate). - */ - useFakeTimers(): JestObjectType, - /** - * Instructs Jest to use the real versions of the standard timer functions. - */ - useRealTimers(): JestObjectType, - /** - * Creates a mock function similar to jest.fn but also tracks calls to - * object[methodName]. - */ - spyOn(object: Object, methodName: string, accessType?: "get" | "set"): JestMockFn, - /** - * Set the default timeout interval for tests and before/after hooks in milliseconds. - * Note: The default timeout interval is 5 seconds if this method is not called. - */ - setTimeout(timeout: number): JestObjectType -}; - -type JestSpyType = { - calls: JestCallsType -}; - -/** Runs this function after every test inside this context */ -declare function afterEach( - fn: (done: () => void) => ?Promise, - timeout?: number -): void; -/** Runs this function before every test inside this context */ -declare function beforeEach( - fn: (done: () => void) => ?Promise, - timeout?: number -): void; -/** Runs this function after all tests have finished inside this context */ -declare function afterAll( - fn: (done: () => void) => ?Promise, - timeout?: number -): void; -/** Runs this function before any tests have started inside this context */ -declare function beforeAll( - fn: (done: () => void) => ?Promise, - timeout?: number -): void; - -/** A context for grouping tests together */ -declare var describe: { - /** - * Creates a block that groups together several related tests in one "test suite" - */ - (name: JestTestName, fn: () => void): void, - - /** - * Only run this describe block - */ - only(name: JestTestName, fn: () => void): void, - - /** - * Skip running this describe block - */ - skip(name: JestTestName, fn: () => void): void -}; - -/** An individual test unit */ -declare var it: { - /** - * An individual test unit - * - * @param {JestTestName} Name of Test - * @param {Function} Test - * @param {number} Timeout for the test, in milliseconds. - */ - ( - name: JestTestName, - fn?: (done: () => void) => ?Promise, - timeout?: number - ): void, - /** - * Only run this test - * - * @param {JestTestName} Name of Test - * @param {Function} Test - * @param {number} Timeout for the test, in milliseconds. - */ - only( - name: JestTestName, - fn?: (done: () => void) => ?Promise, - timeout?: number - ): void, - /** - * Skip running this test - * - * @param {JestTestName} Name of Test - * @param {Function} Test - * @param {number} Timeout for the test, in milliseconds. - */ - skip( - name: JestTestName, - fn?: (done: () => void) => ?Promise, - timeout?: number - ): void, - /** - * Run the test concurrently - * - * @param {JestTestName} Name of Test - * @param {Function} Test - * @param {number} Timeout for the test, in milliseconds. - */ - concurrent( - name: JestTestName, - fn?: (done: () => void) => ?Promise, - timeout?: number - ): void -}; -declare function fit( - name: JestTestName, - fn: (done: () => void) => ?Promise, - timeout?: number -): void; -/** An individual test unit */ -declare var test: typeof it; -/** A disabled group of tests */ -declare var xdescribe: typeof describe; -/** A focused group of tests */ -declare var fdescribe: typeof describe; -/** A disabled individual test */ -declare var xit: typeof it; -/** A disabled individual test */ -declare var xtest: typeof it; - -type JestPrettyFormatColors = { - comment: { close: string, open: string }, - content: { close: string, open: string }, - prop: { close: string, open: string }, - tag: { close: string, open: string }, - value: { close: string, open: string }, -}; - -type JestPrettyFormatIndent = string => string; -type JestPrettyFormatRefs = Array; -type JestPrettyFormatPrint = any => string; -type JestPrettyFormatStringOrNull = string | null; - -type JestPrettyFormatOptions = {| - callToJSON: boolean, - edgeSpacing: string, - escapeRegex: boolean, - highlight: boolean, - indent: number, - maxDepth: number, - min: boolean, - plugins: JestPrettyFormatPlugins, - printFunctionName: boolean, - spacing: string, - theme: {| - comment: string, - content: string, - prop: string, - tag: string, - value: string, - |}, -|}; - -type JestPrettyFormatPlugin = { - print: ( - val: any, - serialize: JestPrettyFormatPrint, - indent: JestPrettyFormatIndent, - opts: JestPrettyFormatOptions, - colors: JestPrettyFormatColors, - ) => string, - test: any => boolean, -}; - -type JestPrettyFormatPlugins = Array; - -/** The expect function is used every time you want to test a value */ -declare var expect: { - /** The object that you want to make assertions against */ - (value: any): JestExpectType & JestPromiseType & EnzymeMatchersType & DomTestingLibraryType, - /** Add additional Jasmine matchers to Jest's roster */ - extend(matchers: { [name: string]: JestMatcher }): void, - /** Add a module that formats application-specific data structures. */ - addSnapshotSerializer(pluginModule: JestPrettyFormatPlugin): void, - assertions(expectedAssertions: number): void, - hasAssertions(): void, - any(value: mixed): JestAsymmetricEqualityType, - anything(): any, - arrayContaining(value: Array): Array, - objectContaining(value: Object): Object, - /** Matches any received string that contains the exact expected string. */ - stringContaining(value: string): string, - stringMatching(value: string | RegExp): string -}; - -// TODO handle return type -// http://jasmine.github.io/2.4/introduction.html#section-Spies -declare function spyOn(value: mixed, method: string): Object; - -/** Holds all functions related to manipulating test runner */ -declare var jest: JestObjectType; - -/** - * The global Jasmine object, this is generally not exposed as the public API, - * using features inside here could break in later versions of Jest. - */ -declare var jasmine: { - DEFAULT_TIMEOUT_INTERVAL: number, - any(value: mixed): JestAsymmetricEqualityType, - anything(): any, - arrayContaining(value: Array): Array, - clock(): JestClockType, - createSpy(name: string): JestSpyType, - createSpyObj( - baseName: string, - methodNames: Array - ): { [methodName: string]: JestSpyType }, - objectContaining(value: Object): Object, - stringMatching(value: string): string -}; diff --git a/flow-typed/npm/js-yaml_vx.x.x.js b/flow-typed/npm/js-yaml_vx.x.x.js deleted file mode 100644 index 20369a609..000000000 --- a/flow-typed/npm/js-yaml_vx.x.x.js +++ /dev/null @@ -1,255 +0,0 @@ -// flow-typed signature: b4cf43d7986b8f53902fd5a0342cd6a2 -// flow-typed version: <>/js-yaml_v^3.8.4/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'js-yaml' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'js-yaml' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'js-yaml/bin/js-yaml' { - declare module.exports: any; -} - -declare module 'js-yaml/dist/js-yaml' { - declare module.exports: any; -} - -declare module 'js-yaml/dist/js-yaml.min' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/common' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/dumper' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/exception' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/loader' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/mark' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema/core' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema/default_full' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema/default_safe' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema/failsafe' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/schema/json' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/binary' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/bool' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/float' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/int' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/js/function' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/js/regexp' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/js/undefined' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/map' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/merge' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/null' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/omap' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/pairs' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/seq' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/set' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/str' { - declare module.exports: any; -} - -declare module 'js-yaml/lib/js-yaml/type/timestamp' { - declare module.exports: any; -} - -// Filename aliases -declare module 'js-yaml/bin/js-yaml.js' { - declare module.exports: $Exports<'js-yaml/bin/js-yaml'>; -} -declare module 'js-yaml/dist/js-yaml.js' { - declare module.exports: $Exports<'js-yaml/dist/js-yaml'>; -} -declare module 'js-yaml/dist/js-yaml.min.js' { - declare module.exports: $Exports<'js-yaml/dist/js-yaml.min'>; -} -declare module 'js-yaml/index' { - declare module.exports: $Exports<'js-yaml'>; -} -declare module 'js-yaml/index.js' { - declare module.exports: $Exports<'js-yaml'>; -} -declare module 'js-yaml/lib/js-yaml.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml'>; -} -declare module 'js-yaml/lib/js-yaml/common.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/common'>; -} -declare module 'js-yaml/lib/js-yaml/dumper.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/dumper'>; -} -declare module 'js-yaml/lib/js-yaml/exception.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/exception'>; -} -declare module 'js-yaml/lib/js-yaml/loader.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/loader'>; -} -declare module 'js-yaml/lib/js-yaml/mark.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/mark'>; -} -declare module 'js-yaml/lib/js-yaml/schema.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema'>; -} -declare module 'js-yaml/lib/js-yaml/schema/core.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema/core'>; -} -declare module 'js-yaml/lib/js-yaml/schema/default_full.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema/default_full'>; -} -declare module 'js-yaml/lib/js-yaml/schema/default_safe.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema/default_safe'>; -} -declare module 'js-yaml/lib/js-yaml/schema/failsafe.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema/failsafe'>; -} -declare module 'js-yaml/lib/js-yaml/schema/json.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/schema/json'>; -} -declare module 'js-yaml/lib/js-yaml/type.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type'>; -} -declare module 'js-yaml/lib/js-yaml/type/binary.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/binary'>; -} -declare module 'js-yaml/lib/js-yaml/type/bool.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/bool'>; -} -declare module 'js-yaml/lib/js-yaml/type/float.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/float'>; -} -declare module 'js-yaml/lib/js-yaml/type/int.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/int'>; -} -declare module 'js-yaml/lib/js-yaml/type/js/function.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/js/function'>; -} -declare module 'js-yaml/lib/js-yaml/type/js/regexp.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/js/regexp'>; -} -declare module 'js-yaml/lib/js-yaml/type/js/undefined.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/js/undefined'>; -} -declare module 'js-yaml/lib/js-yaml/type/map.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/map'>; -} -declare module 'js-yaml/lib/js-yaml/type/merge.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/merge'>; -} -declare module 'js-yaml/lib/js-yaml/type/null.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/null'>; -} -declare module 'js-yaml/lib/js-yaml/type/omap.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/omap'>; -} -declare module 'js-yaml/lib/js-yaml/type/pairs.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/pairs'>; -} -declare module 'js-yaml/lib/js-yaml/type/seq.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/seq'>; -} -declare module 'js-yaml/lib/js-yaml/type/set.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/set'>; -} -declare module 'js-yaml/lib/js-yaml/type/str.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/str'>; -} -declare module 'js-yaml/lib/js-yaml/type/timestamp.js' { - declare module.exports: $Exports<'js-yaml/lib/js-yaml/type/timestamp'>; -} diff --git a/flow-typed/npm/jsonwebtoken_vx.x.x.js b/flow-typed/npm/jsonwebtoken_vx.x.x.js deleted file mode 100644 index 911a76b8f..000000000 --- a/flow-typed/npm/jsonwebtoken_vx.x.x.js +++ /dev/null @@ -1,227 +0,0 @@ -// flow-typed signature: 238f271634c3c75a3b50c492fcac449f -// flow-typed version: <>/jsonwebtoken_v^7.4.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'jsonwebtoken' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'jsonwebtoken' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'jsonwebtoken/decode' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/lib/JsonWebTokenError' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/lib/NotBeforeError' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/lib/timespan' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/lib/TokenExpiredError' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/sign' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/async_sign.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/buffer.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/encoding.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/expires_format.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/iat.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/invalid_exp.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/issue_147.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/issue_196.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/issue_304.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/issue_70.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/jwt.hs.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/jwt.rs.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/keyid.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/non_object_values.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/noTimestamp.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/rsa-public-key.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/set_headers.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/undefined_secretOrPublickey.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/util/fakeDate' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/verify.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/test/wrong_alg.tests' { - declare module.exports: any; -} - -declare module 'jsonwebtoken/verify' { - declare module.exports: any; -} - -// Filename aliases -declare module 'jsonwebtoken/decode.js' { - declare module.exports: $Exports<'jsonwebtoken/decode'>; -} -declare module 'jsonwebtoken/index' { - declare module.exports: $Exports<'jsonwebtoken'>; -} -declare module 'jsonwebtoken/index.js' { - declare module.exports: $Exports<'jsonwebtoken'>; -} -declare module 'jsonwebtoken/lib/JsonWebTokenError.js' { - declare module.exports: $Exports<'jsonwebtoken/lib/JsonWebTokenError'>; -} -declare module 'jsonwebtoken/lib/NotBeforeError.js' { - declare module.exports: $Exports<'jsonwebtoken/lib/NotBeforeError'>; -} -declare module 'jsonwebtoken/lib/timespan.js' { - declare module.exports: $Exports<'jsonwebtoken/lib/timespan'>; -} -declare module 'jsonwebtoken/lib/TokenExpiredError.js' { - declare module.exports: $Exports<'jsonwebtoken/lib/TokenExpiredError'>; -} -declare module 'jsonwebtoken/sign.js' { - declare module.exports: $Exports<'jsonwebtoken/sign'>; -} -declare module 'jsonwebtoken/test/async_sign.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/async_sign.tests'>; -} -declare module 'jsonwebtoken/test/buffer.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/buffer.tests'>; -} -declare module 'jsonwebtoken/test/encoding.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/encoding.tests'>; -} -declare module 'jsonwebtoken/test/expires_format.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/expires_format.tests'>; -} -declare module 'jsonwebtoken/test/iat.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/iat.tests'>; -} -declare module 'jsonwebtoken/test/invalid_exp.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/invalid_exp.tests'>; -} -declare module 'jsonwebtoken/test/issue_147.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/issue_147.tests'>; -} -declare module 'jsonwebtoken/test/issue_196.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/issue_196.tests'>; -} -declare module 'jsonwebtoken/test/issue_304.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/issue_304.tests'>; -} -declare module 'jsonwebtoken/test/issue_70.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/issue_70.tests'>; -} -declare module 'jsonwebtoken/test/jwt.hs.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/jwt.hs.tests'>; -} -declare module 'jsonwebtoken/test/jwt.rs.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/jwt.rs.tests'>; -} -declare module 'jsonwebtoken/test/keyid.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/keyid.tests'>; -} -declare module 'jsonwebtoken/test/non_object_values.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/non_object_values.tests'>; -} -declare module 'jsonwebtoken/test/noTimestamp.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/noTimestamp.tests'>; -} -declare module 'jsonwebtoken/test/rsa-public-key.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/rsa-public-key.tests'>; -} -declare module 'jsonwebtoken/test/set_headers.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/set_headers.tests'>; -} -declare module 'jsonwebtoken/test/undefined_secretOrPublickey.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/undefined_secretOrPublickey.tests'>; -} -declare module 'jsonwebtoken/test/util/fakeDate.js' { - declare module.exports: $Exports<'jsonwebtoken/test/util/fakeDate'>; -} -declare module 'jsonwebtoken/test/verify.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/verify.tests'>; -} -declare module 'jsonwebtoken/test/wrong_alg.tests.js' { - declare module.exports: $Exports<'jsonwebtoken/test/wrong_alg.tests'>; -} -declare module 'jsonwebtoken/verify.js' { - declare module.exports: $Exports<'jsonwebtoken/verify'>; -} diff --git a/flow-typed/npm/lint-staged_vx.x.x.js b/flow-typed/npm/lint-staged_vx.x.x.js deleted file mode 100644 index a94d0beea..000000000 --- a/flow-typed/npm/lint-staged_vx.x.x.js +++ /dev/null @@ -1,108 +0,0 @@ -// flow-typed signature: f07a7ba2044e03df044a32b2b5e8a812 -// flow-typed version: <>/lint-staged_v^3.2.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'lint-staged' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'lint-staged' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'lint-staged/src/findBin' { - declare module.exports: any; -} - -declare module 'lint-staged/src/generateTasks' { - declare module.exports: any; -} - -declare module 'lint-staged/src/index' { - declare module.exports: any; -} - -declare module 'lint-staged/src/resolvePaths' { - declare module.exports: any; -} - -declare module 'lint-staged/src/runScript' { - declare module.exports: any; -} - -declare module 'lint-staged/test/__fixtures__/test' { - declare module.exports: any; -} - -declare module 'lint-staged/test/findBin.spec' { - declare module.exports: any; -} - -declare module 'lint-staged/test/generateTasks.spec' { - declare module.exports: any; -} - -declare module 'lint-staged/test/resolvePaths.spec' { - declare module.exports: any; -} - -declare module 'lint-staged/test/runScript.spec' { - declare module.exports: any; -} - -declare module 'lint-staged/wallaby' { - declare module.exports: any; -} - -// Filename aliases -declare module 'lint-staged/index' { - declare module.exports: $Exports<'lint-staged'>; -} -declare module 'lint-staged/index.js' { - declare module.exports: $Exports<'lint-staged'>; -} -declare module 'lint-staged/src/findBin.js' { - declare module.exports: $Exports<'lint-staged/src/findBin'>; -} -declare module 'lint-staged/src/generateTasks.js' { - declare module.exports: $Exports<'lint-staged/src/generateTasks'>; -} -declare module 'lint-staged/src/index.js' { - declare module.exports: $Exports<'lint-staged/src/index'>; -} -declare module 'lint-staged/src/resolvePaths.js' { - declare module.exports: $Exports<'lint-staged/src/resolvePaths'>; -} -declare module 'lint-staged/src/runScript.js' { - declare module.exports: $Exports<'lint-staged/src/runScript'>; -} -declare module 'lint-staged/test/__fixtures__/test.js' { - declare module.exports: $Exports<'lint-staged/test/__fixtures__/test'>; -} -declare module 'lint-staged/test/findBin.spec.js' { - declare module.exports: $Exports<'lint-staged/test/findBin.spec'>; -} -declare module 'lint-staged/test/generateTasks.spec.js' { - declare module.exports: $Exports<'lint-staged/test/generateTasks.spec'>; -} -declare module 'lint-staged/test/resolvePaths.spec.js' { - declare module.exports: $Exports<'lint-staged/test/resolvePaths.spec'>; -} -declare module 'lint-staged/test/runScript.spec.js' { - declare module.exports: $Exports<'lint-staged/test/runScript.spec'>; -} -declare module 'lint-staged/wallaby.js' { - declare module.exports: $Exports<'lint-staged/wallaby'>; -} diff --git a/flow-typed/npm/morgan_vx.x.x.js b/flow-typed/npm/morgan_vx.x.x.js deleted file mode 100644 index 70d351300..000000000 --- a/flow-typed/npm/morgan_vx.x.x.js +++ /dev/null @@ -1,33 +0,0 @@ -// flow-typed signature: 37570f80bc4d5061a615dd1fb46f76cd -// flow-typed version: <>/morgan_v1.8.2/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'morgan' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'morgan' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ - - -// Filename aliases -declare module 'morgan/index' { - declare module.exports: $Exports<'morgan'>; -} -declare module 'morgan/index.js' { - declare module.exports: $Exports<'morgan'>; -} diff --git a/flow-typed/npm/nano_vx.x.x.js b/flow-typed/npm/nano_vx.x.x.js deleted file mode 100644 index f1d3a8d22..000000000 --- a/flow-typed/npm/nano_vx.x.x.js +++ /dev/null @@ -1,564 +0,0 @@ -// flow-typed signature: 53d029c66ef4bc9f899a3d89723e39ff -// flow-typed version: <>/nano_v^6.3.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'nano' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'nano' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'nano/examples/bulk_transform' { - declare module.exports: any; -} - -declare module 'nano/examples/express' { - declare module.exports: any; -} - -declare module 'nano/examples/lazy_creation_of_views' { - declare module.exports: any; -} - -declare module 'nano/examples/lazy_db_creation_and_replication' { - declare module.exports: any; -} - -declare module 'nano/examples/pipe' { - declare module.exports: any; -} - -declare module 'nano/lib/logger' { - declare module.exports: any; -} - -declare module 'nano/lib/nano' { - declare module.exports: any; -} - -declare module 'nano/tests/helpers/index' { - declare module.exports: any; -} - -declare module 'nano/tests/helpers/integration' { - declare module.exports: any; -} - -declare module 'nano/tests/helpers/unit' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/attachment/destroy' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/attachment/get' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/attachment/insert' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/attachment/pipe' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/attachment/update' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/changes' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/compact' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/create-and-destroy' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/follow' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/get' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/list' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/replicate' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/database/replicator' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/atomic' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/compact' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/list' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/multiple' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/query' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/search' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/design/show' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/bulk' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/copy' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/destroy' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/fetch_revs' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/fetch' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/get' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/head' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/insert' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/list' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/document/update' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/multipart/get' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/multipart/insert' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/config' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/cookie' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/error' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/headers' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/log' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/shared/nano' { - declare module.exports: any; -} - -declare module 'nano/tests/integration/util/uuid' { - declare module.exports: any; -} - -declare module 'nano/tests/intercept/design/search' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/attachment/destroy' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/attachment/get' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/attachment/insert' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/changes' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/compact' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/create' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/destroy' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/follow' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/get' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/list' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/replicate' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/replicator' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/database/updates' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/atomic' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/compact' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/list' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/search' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/show' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/spatial' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/design/view' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/document/bulk' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/document/copy' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/multipart/get' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/multipart/insert' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/shared/error' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/shared/follow-updates' { - declare module.exports: any; -} - -declare module 'nano/tests/unit/shared/jar' { - declare module.exports: any; -} - -// Filename aliases -declare module 'nano/examples/bulk_transform.js' { - declare module.exports: $Exports<'nano/examples/bulk_transform'>; -} -declare module 'nano/examples/express.js' { - declare module.exports: $Exports<'nano/examples/express'>; -} -declare module 'nano/examples/lazy_creation_of_views.js' { - declare module.exports: $Exports<'nano/examples/lazy_creation_of_views'>; -} -declare module 'nano/examples/lazy_db_creation_and_replication.js' { - declare module.exports: $Exports<'nano/examples/lazy_db_creation_and_replication'>; -} -declare module 'nano/examples/pipe.js' { - declare module.exports: $Exports<'nano/examples/pipe'>; -} -declare module 'nano/lib/logger.js' { - declare module.exports: $Exports<'nano/lib/logger'>; -} -declare module 'nano/lib/nano.js' { - declare module.exports: $Exports<'nano/lib/nano'>; -} -declare module 'nano/tests/helpers/index.js' { - declare module.exports: $Exports<'nano/tests/helpers/index'>; -} -declare module 'nano/tests/helpers/integration.js' { - declare module.exports: $Exports<'nano/tests/helpers/integration'>; -} -declare module 'nano/tests/helpers/unit.js' { - declare module.exports: $Exports<'nano/tests/helpers/unit'>; -} -declare module 'nano/tests/integration/attachment/destroy.js' { - declare module.exports: $Exports<'nano/tests/integration/attachment/destroy'>; -} -declare module 'nano/tests/integration/attachment/get.js' { - declare module.exports: $Exports<'nano/tests/integration/attachment/get'>; -} -declare module 'nano/tests/integration/attachment/insert.js' { - declare module.exports: $Exports<'nano/tests/integration/attachment/insert'>; -} -declare module 'nano/tests/integration/attachment/pipe.js' { - declare module.exports: $Exports<'nano/tests/integration/attachment/pipe'>; -} -declare module 'nano/tests/integration/attachment/update.js' { - declare module.exports: $Exports<'nano/tests/integration/attachment/update'>; -} -declare module 'nano/tests/integration/database/changes.js' { - declare module.exports: $Exports<'nano/tests/integration/database/changes'>; -} -declare module 'nano/tests/integration/database/compact.js' { - declare module.exports: $Exports<'nano/tests/integration/database/compact'>; -} -declare module 'nano/tests/integration/database/create-and-destroy.js' { - declare module.exports: $Exports<'nano/tests/integration/database/create-and-destroy'>; -} -declare module 'nano/tests/integration/database/follow.js' { - declare module.exports: $Exports<'nano/tests/integration/database/follow'>; -} -declare module 'nano/tests/integration/database/get.js' { - declare module.exports: $Exports<'nano/tests/integration/database/get'>; -} -declare module 'nano/tests/integration/database/list.js' { - declare module.exports: $Exports<'nano/tests/integration/database/list'>; -} -declare module 'nano/tests/integration/database/replicate.js' { - declare module.exports: $Exports<'nano/tests/integration/database/replicate'>; -} -declare module 'nano/tests/integration/database/replicator.js' { - declare module.exports: $Exports<'nano/tests/integration/database/replicator'>; -} -declare module 'nano/tests/integration/design/atomic.js' { - declare module.exports: $Exports<'nano/tests/integration/design/atomic'>; -} -declare module 'nano/tests/integration/design/compact.js' { - declare module.exports: $Exports<'nano/tests/integration/design/compact'>; -} -declare module 'nano/tests/integration/design/list.js' { - declare module.exports: $Exports<'nano/tests/integration/design/list'>; -} -declare module 'nano/tests/integration/design/multiple.js' { - declare module.exports: $Exports<'nano/tests/integration/design/multiple'>; -} -declare module 'nano/tests/integration/design/query.js' { - declare module.exports: $Exports<'nano/tests/integration/design/query'>; -} -declare module 'nano/tests/integration/design/search.js' { - declare module.exports: $Exports<'nano/tests/integration/design/search'>; -} -declare module 'nano/tests/integration/design/show.js' { - declare module.exports: $Exports<'nano/tests/integration/design/show'>; -} -declare module 'nano/tests/integration/document/bulk.js' { - declare module.exports: $Exports<'nano/tests/integration/document/bulk'>; -} -declare module 'nano/tests/integration/document/copy.js' { - declare module.exports: $Exports<'nano/tests/integration/document/copy'>; -} -declare module 'nano/tests/integration/document/destroy.js' { - declare module.exports: $Exports<'nano/tests/integration/document/destroy'>; -} -declare module 'nano/tests/integration/document/fetch_revs.js' { - declare module.exports: $Exports<'nano/tests/integration/document/fetch_revs'>; -} -declare module 'nano/tests/integration/document/fetch.js' { - declare module.exports: $Exports<'nano/tests/integration/document/fetch'>; -} -declare module 'nano/tests/integration/document/get.js' { - declare module.exports: $Exports<'nano/tests/integration/document/get'>; -} -declare module 'nano/tests/integration/document/head.js' { - declare module.exports: $Exports<'nano/tests/integration/document/head'>; -} -declare module 'nano/tests/integration/document/insert.js' { - declare module.exports: $Exports<'nano/tests/integration/document/insert'>; -} -declare module 'nano/tests/integration/document/list.js' { - declare module.exports: $Exports<'nano/tests/integration/document/list'>; -} -declare module 'nano/tests/integration/document/update.js' { - declare module.exports: $Exports<'nano/tests/integration/document/update'>; -} -declare module 'nano/tests/integration/multipart/get.js' { - declare module.exports: $Exports<'nano/tests/integration/multipart/get'>; -} -declare module 'nano/tests/integration/multipart/insert.js' { - declare module.exports: $Exports<'nano/tests/integration/multipart/insert'>; -} -declare module 'nano/tests/integration/shared/config.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/config'>; -} -declare module 'nano/tests/integration/shared/cookie.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/cookie'>; -} -declare module 'nano/tests/integration/shared/error.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/error'>; -} -declare module 'nano/tests/integration/shared/headers.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/headers'>; -} -declare module 'nano/tests/integration/shared/log.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/log'>; -} -declare module 'nano/tests/integration/shared/nano.js' { - declare module.exports: $Exports<'nano/tests/integration/shared/nano'>; -} -declare module 'nano/tests/integration/util/uuid.js' { - declare module.exports: $Exports<'nano/tests/integration/util/uuid'>; -} -declare module 'nano/tests/intercept/design/search.js' { - declare module.exports: $Exports<'nano/tests/intercept/design/search'>; -} -declare module 'nano/tests/unit/attachment/destroy.js' { - declare module.exports: $Exports<'nano/tests/unit/attachment/destroy'>; -} -declare module 'nano/tests/unit/attachment/get.js' { - declare module.exports: $Exports<'nano/tests/unit/attachment/get'>; -} -declare module 'nano/tests/unit/attachment/insert.js' { - declare module.exports: $Exports<'nano/tests/unit/attachment/insert'>; -} -declare module 'nano/tests/unit/database/changes.js' { - declare module.exports: $Exports<'nano/tests/unit/database/changes'>; -} -declare module 'nano/tests/unit/database/compact.js' { - declare module.exports: $Exports<'nano/tests/unit/database/compact'>; -} -declare module 'nano/tests/unit/database/create.js' { - declare module.exports: $Exports<'nano/tests/unit/database/create'>; -} -declare module 'nano/tests/unit/database/destroy.js' { - declare module.exports: $Exports<'nano/tests/unit/database/destroy'>; -} -declare module 'nano/tests/unit/database/follow.js' { - declare module.exports: $Exports<'nano/tests/unit/database/follow'>; -} -declare module 'nano/tests/unit/database/get.js' { - declare module.exports: $Exports<'nano/tests/unit/database/get'>; -} -declare module 'nano/tests/unit/database/list.js' { - declare module.exports: $Exports<'nano/tests/unit/database/list'>; -} -declare module 'nano/tests/unit/database/replicate.js' { - declare module.exports: $Exports<'nano/tests/unit/database/replicate'>; -} -declare module 'nano/tests/unit/database/replicator.js' { - declare module.exports: $Exports<'nano/tests/unit/database/replicator'>; -} -declare module 'nano/tests/unit/database/updates.js' { - declare module.exports: $Exports<'nano/tests/unit/database/updates'>; -} -declare module 'nano/tests/unit/design/atomic.js' { - declare module.exports: $Exports<'nano/tests/unit/design/atomic'>; -} -declare module 'nano/tests/unit/design/compact.js' { - declare module.exports: $Exports<'nano/tests/unit/design/compact'>; -} -declare module 'nano/tests/unit/design/list.js' { - declare module.exports: $Exports<'nano/tests/unit/design/list'>; -} -declare module 'nano/tests/unit/design/search.js' { - declare module.exports: $Exports<'nano/tests/unit/design/search'>; -} -declare module 'nano/tests/unit/design/show.js' { - declare module.exports: $Exports<'nano/tests/unit/design/show'>; -} -declare module 'nano/tests/unit/design/spatial.js' { - declare module.exports: $Exports<'nano/tests/unit/design/spatial'>; -} -declare module 'nano/tests/unit/design/view.js' { - declare module.exports: $Exports<'nano/tests/unit/design/view'>; -} -declare module 'nano/tests/unit/document/bulk.js' { - declare module.exports: $Exports<'nano/tests/unit/document/bulk'>; -} -declare module 'nano/tests/unit/document/copy.js' { - declare module.exports: $Exports<'nano/tests/unit/document/copy'>; -} -declare module 'nano/tests/unit/multipart/get.js' { - declare module.exports: $Exports<'nano/tests/unit/multipart/get'>; -} -declare module 'nano/tests/unit/multipart/insert.js' { - declare module.exports: $Exports<'nano/tests/unit/multipart/insert'>; -} -declare module 'nano/tests/unit/shared/error.js' { - declare module.exports: $Exports<'nano/tests/unit/shared/error'>; -} -declare module 'nano/tests/unit/shared/follow-updates.js' { - declare module.exports: $Exports<'nano/tests/unit/shared/follow-updates'>; -} -declare module 'nano/tests/unit/shared/jar.js' { - declare module.exports: $Exports<'nano/tests/unit/shared/jar'>; -} diff --git a/flow-typed/npm/node-fetch_vx.x.x.js b/flow-typed/npm/node-fetch_vx.x.x.js deleted file mode 100644 index 95b280a6d..000000000 --- a/flow-typed/npm/node-fetch_vx.x.x.js +++ /dev/null @@ -1,80 +0,0 @@ -// flow-typed signature: 2c6e6ff7ad0b962f3c754dc69a3ed3bb -// flow-typed version: <>/node-fetch_v^1.6.3/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'node-fetch' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'node-fetch' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'node-fetch/lib/body' { - declare module.exports: any; -} - -declare module 'node-fetch/lib/fetch-error' { - declare module.exports: any; -} - -declare module 'node-fetch/lib/headers' { - declare module.exports: any; -} - -declare module 'node-fetch/lib/request' { - declare module.exports: any; -} - -declare module 'node-fetch/lib/response' { - declare module.exports: any; -} - -declare module 'node-fetch/test/server' { - declare module.exports: any; -} - -declare module 'node-fetch/test/test' { - declare module.exports: any; -} - -// Filename aliases -declare module 'node-fetch/index' { - declare module.exports: $Exports<'node-fetch'>; -} -declare module 'node-fetch/index.js' { - declare module.exports: $Exports<'node-fetch'>; -} -declare module 'node-fetch/lib/body.js' { - declare module.exports: $Exports<'node-fetch/lib/body'>; -} -declare module 'node-fetch/lib/fetch-error.js' { - declare module.exports: $Exports<'node-fetch/lib/fetch-error'>; -} -declare module 'node-fetch/lib/headers.js' { - declare module.exports: $Exports<'node-fetch/lib/headers'>; -} -declare module 'node-fetch/lib/request.js' { - declare module.exports: $Exports<'node-fetch/lib/request'>; -} -declare module 'node-fetch/lib/response.js' { - declare module.exports: $Exports<'node-fetch/lib/response'>; -} -declare module 'node-fetch/test/server.js' { - declare module.exports: $Exports<'node-fetch/test/server'>; -} -declare module 'node-fetch/test/test.js' { - declare module.exports: $Exports<'node-fetch/test/test'>; -} diff --git a/flow-typed/npm/nodemon_vx.x.x.js b/flow-typed/npm/nodemon_vx.x.x.js deleted file mode 100644 index ce60df90c..000000000 --- a/flow-typed/npm/nodemon_vx.x.x.js +++ /dev/null @@ -1,214 +0,0 @@ -// flow-typed signature: b8d9561c71ecda9042aa95e3bacb7474 -// flow-typed version: <>/nodemon_v^1.11.0/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'nodemon' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'nodemon' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'nodemon/bin/nodemon' { - declare module.exports: any; -} - -declare module 'nodemon/lib/cli/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/cli/parse' { - declare module.exports: any; -} - -declare module 'nodemon/lib/config/command' { - declare module.exports: any; -} - -declare module 'nodemon/lib/config/defaults' { - declare module.exports: any; -} - -declare module 'nodemon/lib/config/exec' { - declare module.exports: any; -} - -declare module 'nodemon/lib/config/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/config/load' { - declare module.exports: any; -} - -declare module 'nodemon/lib/help/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/monitor/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/monitor/match' { - declare module.exports: any; -} - -declare module 'nodemon/lib/monitor/run' { - declare module.exports: any; -} - -declare module 'nodemon/lib/monitor/watch' { - declare module.exports: any; -} - -declare module 'nodemon/lib/nodemon' { - declare module.exports: any; -} - -declare module 'nodemon/lib/rules/add' { - declare module.exports: any; -} - -declare module 'nodemon/lib/rules/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/rules/parse' { - declare module.exports: any; -} - -declare module 'nodemon/lib/spawn' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/bus' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/clone' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/colour' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/index' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/log' { - declare module.exports: any; -} - -declare module 'nodemon/lib/utils/merge' { - declare module.exports: any; -} - -declare module 'nodemon/lib/version' { - declare module.exports: any; -} - -declare module 'nodemon/web/index' { - declare module.exports: any; -} - -// Filename aliases -declare module 'nodemon/bin/nodemon.js' { - declare module.exports: $Exports<'nodemon/bin/nodemon'>; -} -declare module 'nodemon/lib/cli/index.js' { - declare module.exports: $Exports<'nodemon/lib/cli/index'>; -} -declare module 'nodemon/lib/cli/parse.js' { - declare module.exports: $Exports<'nodemon/lib/cli/parse'>; -} -declare module 'nodemon/lib/config/command.js' { - declare module.exports: $Exports<'nodemon/lib/config/command'>; -} -declare module 'nodemon/lib/config/defaults.js' { - declare module.exports: $Exports<'nodemon/lib/config/defaults'>; -} -declare module 'nodemon/lib/config/exec.js' { - declare module.exports: $Exports<'nodemon/lib/config/exec'>; -} -declare module 'nodemon/lib/config/index.js' { - declare module.exports: $Exports<'nodemon/lib/config/index'>; -} -declare module 'nodemon/lib/config/load.js' { - declare module.exports: $Exports<'nodemon/lib/config/load'>; -} -declare module 'nodemon/lib/help/index.js' { - declare module.exports: $Exports<'nodemon/lib/help/index'>; -} -declare module 'nodemon/lib/index.js' { - declare module.exports: $Exports<'nodemon/lib/index'>; -} -declare module 'nodemon/lib/monitor/index.js' { - declare module.exports: $Exports<'nodemon/lib/monitor/index'>; -} -declare module 'nodemon/lib/monitor/match.js' { - declare module.exports: $Exports<'nodemon/lib/monitor/match'>; -} -declare module 'nodemon/lib/monitor/run.js' { - declare module.exports: $Exports<'nodemon/lib/monitor/run'>; -} -declare module 'nodemon/lib/monitor/watch.js' { - declare module.exports: $Exports<'nodemon/lib/monitor/watch'>; -} -declare module 'nodemon/lib/nodemon.js' { - declare module.exports: $Exports<'nodemon/lib/nodemon'>; -} -declare module 'nodemon/lib/rules/add.js' { - declare module.exports: $Exports<'nodemon/lib/rules/add'>; -} -declare module 'nodemon/lib/rules/index.js' { - declare module.exports: $Exports<'nodemon/lib/rules/index'>; -} -declare module 'nodemon/lib/rules/parse.js' { - declare module.exports: $Exports<'nodemon/lib/rules/parse'>; -} -declare module 'nodemon/lib/spawn.js' { - declare module.exports: $Exports<'nodemon/lib/spawn'>; -} -declare module 'nodemon/lib/utils/bus.js' { - declare module.exports: $Exports<'nodemon/lib/utils/bus'>; -} -declare module 'nodemon/lib/utils/clone.js' { - declare module.exports: $Exports<'nodemon/lib/utils/clone'>; -} -declare module 'nodemon/lib/utils/colour.js' { - declare module.exports: $Exports<'nodemon/lib/utils/colour'>; -} -declare module 'nodemon/lib/utils/index.js' { - declare module.exports: $Exports<'nodemon/lib/utils/index'>; -} -declare module 'nodemon/lib/utils/log.js' { - declare module.exports: $Exports<'nodemon/lib/utils/log'>; -} -declare module 'nodemon/lib/utils/merge.js' { - declare module.exports: $Exports<'nodemon/lib/utils/merge'>; -} -declare module 'nodemon/lib/version.js' { - declare module.exports: $Exports<'nodemon/lib/version'>; -} -declare module 'nodemon/web/index.js' { - declare module.exports: $Exports<'nodemon/web/index'>; -} diff --git a/flow-typed/npm/pre-commit_vx.x.x.js b/flow-typed/npm/pre-commit_vx.x.x.js deleted file mode 100644 index da2298cc1..000000000 --- a/flow-typed/npm/pre-commit_vx.x.x.js +++ /dev/null @@ -1,52 +0,0 @@ -// flow-typed signature: 9d8d0dd50b7d641eac4acba17930ba97 -// flow-typed version: <>/pre-commit_v^1.1.3/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'pre-commit' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'pre-commit' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'pre-commit/install' { - declare module.exports: any; -} - -declare module 'pre-commit/test' { - declare module.exports: any; -} - -declare module 'pre-commit/uninstall' { - declare module.exports: any; -} - -// Filename aliases -declare module 'pre-commit/index' { - declare module.exports: $Exports<'pre-commit'>; -} -declare module 'pre-commit/index.js' { - declare module.exports: $Exports<'pre-commit'>; -} -declare module 'pre-commit/install.js' { - declare module.exports: $Exports<'pre-commit/install'>; -} -declare module 'pre-commit/test.js' { - declare module.exports: $Exports<'pre-commit/test'>; -} -declare module 'pre-commit/uninstall.js' { - declare module.exports: $Exports<'pre-commit/uninstall'>; -} diff --git a/flow-typed/npm/prettier_vx.x.x.js b/flow-typed/npm/prettier_vx.x.x.js deleted file mode 100644 index 8573414e0..000000000 --- a/flow-typed/npm/prettier_vx.x.x.js +++ /dev/null @@ -1,73 +0,0 @@ -// flow-typed signature: 5805d6823e1a1ddddfcaa0cbe78e201d -// flow-typed version: <>/prettier_v^1.4.4/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'prettier' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'prettier' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'prettier/bin/prettier' { - declare module.exports: any; -} - -declare module 'prettier/parser-babylon' { - declare module.exports: any; -} - -declare module 'prettier/parser-flow' { - declare module.exports: any; -} - -declare module 'prettier/parser-graphql' { - declare module.exports: any; -} - -declare module 'prettier/parser-postcss' { - declare module.exports: any; -} - -declare module 'prettier/parser-typescript' { - declare module.exports: any; -} - -// Filename aliases -declare module 'prettier/bin/prettier.js' { - declare module.exports: $Exports<'prettier/bin/prettier'>; -} -declare module 'prettier/index' { - declare module.exports: $Exports<'prettier'>; -} -declare module 'prettier/index.js' { - declare module.exports: $Exports<'prettier'>; -} -declare module 'prettier/parser-babylon.js' { - declare module.exports: $Exports<'prettier/parser-babylon'>; -} -declare module 'prettier/parser-flow.js' { - declare module.exports: $Exports<'prettier/parser-flow'>; -} -declare module 'prettier/parser-graphql.js' { - declare module.exports: $Exports<'prettier/parser-graphql'>; -} -declare module 'prettier/parser-postcss.js' { - declare module.exports: $Exports<'prettier/parser-postcss'>; -} -declare module 'prettier/parser-typescript.js' { - declare module.exports: $Exports<'prettier/parser-typescript'>; -} diff --git a/flow-typed/npm/rimraf_vx.x.x.js b/flow-typed/npm/rimraf_vx.x.x.js deleted file mode 100644 index 46d6c4b87..000000000 --- a/flow-typed/npm/rimraf_vx.x.x.js +++ /dev/null @@ -1,39 +0,0 @@ -// flow-typed signature: 053866bfc2ecbad7ff18cb3ff150effa -// flow-typed version: <>/rimraf_v^2.5.4/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'rimraf' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'rimraf' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'rimraf/bin' { - declare module.exports: any; -} - -declare module 'rimraf/rimraf' { - declare module.exports: any; -} - -// Filename aliases -declare module 'rimraf/bin.js' { - declare module.exports: $Exports<'rimraf/bin'>; -} -declare module 'rimraf/rimraf.js' { - declare module.exports: $Exports<'rimraf/rimraf'>; -} diff --git a/flow-typed/npm/ssh2_vx.x.x.js b/flow-typed/npm/ssh2_vx.x.x.js deleted file mode 100644 index 5112ed5ec..000000000 --- a/flow-typed/npm/ssh2_vx.x.x.js +++ /dev/null @@ -1,109 +0,0 @@ -// flow-typed signature: a07312f58f7c196eb55ef73187a2ae4a -// flow-typed version: <>/ssh2_v^0.5.5/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'ssh2' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'ssh2' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'ssh2/examples/server-chat' { - declare module.exports: any; -} - -declare module 'ssh2/examples/sftp-server-download-only' { - declare module.exports: any; -} - -declare module 'ssh2/lib/agent' { - declare module.exports: any; -} - -declare module 'ssh2/lib/Channel' { - declare module.exports: any; -} - -declare module 'ssh2/lib/client' { - declare module.exports: any; -} - -declare module 'ssh2/lib/keepalivemgr' { - declare module.exports: any; -} - -declare module 'ssh2/lib/server' { - declare module.exports: any; -} - -declare module 'ssh2/lib/SFTPWrapper' { - declare module.exports: any; -} - -declare module 'ssh2/lib/utils' { - declare module.exports: any; -} - -declare module 'ssh2/test/test-client-server' { - declare module.exports: any; -} - -declare module 'ssh2/test/test-openssh' { - declare module.exports: any; -} - -declare module 'ssh2/test/test' { - declare module.exports: any; -} - -// Filename aliases -declare module 'ssh2/examples/server-chat.js' { - declare module.exports: $Exports<'ssh2/examples/server-chat'>; -} -declare module 'ssh2/examples/sftp-server-download-only.js' { - declare module.exports: $Exports<'ssh2/examples/sftp-server-download-only'>; -} -declare module 'ssh2/lib/agent.js' { - declare module.exports: $Exports<'ssh2/lib/agent'>; -} -declare module 'ssh2/lib/Channel.js' { - declare module.exports: $Exports<'ssh2/lib/Channel'>; -} -declare module 'ssh2/lib/client.js' { - declare module.exports: $Exports<'ssh2/lib/client'>; -} -declare module 'ssh2/lib/keepalivemgr.js' { - declare module.exports: $Exports<'ssh2/lib/keepalivemgr'>; -} -declare module 'ssh2/lib/server.js' { - declare module.exports: $Exports<'ssh2/lib/server'>; -} -declare module 'ssh2/lib/SFTPWrapper.js' { - declare module.exports: $Exports<'ssh2/lib/SFTPWrapper'>; -} -declare module 'ssh2/lib/utils.js' { - declare module.exports: $Exports<'ssh2/lib/utils'>; -} -declare module 'ssh2/test/test-client-server.js' { - declare module.exports: $Exports<'ssh2/test/test-client-server'>; -} -declare module 'ssh2/test/test-openssh.js' { - declare module.exports: $Exports<'ssh2/test/test-openssh'>; -} -declare module 'ssh2/test/test.js' { - declare module.exports: $Exports<'ssh2/test/test'>; -} diff --git a/flow-typed/npm/sshpk_vx.x.x.js b/flow-typed/npm/sshpk_vx.x.x.js deleted file mode 100644 index 9ab8a5338..000000000 --- a/flow-typed/npm/sshpk_vx.x.x.js +++ /dev/null @@ -1,186 +0,0 @@ -// flow-typed signature: 80428e741e02457a1e73a334b462c2a4 -// flow-typed version: <>/sshpk_v^1.13.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'sshpk' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'sshpk' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'sshpk/lib/algs' { - declare module.exports: any; -} - -declare module 'sshpk/lib/certificate' { - declare module.exports: any; -} - -declare module 'sshpk/lib/dhe' { - declare module.exports: any; -} - -declare module 'sshpk/lib/ed-compat' { - declare module.exports: any; -} - -declare module 'sshpk/lib/errors' { - declare module.exports: any; -} - -declare module 'sshpk/lib/fingerprint' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/auto' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/openssh-cert' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/pem' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/pkcs1' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/pkcs8' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/rfc4253' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/ssh-private' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/ssh' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/x509-pem' { - declare module.exports: any; -} - -declare module 'sshpk/lib/formats/x509' { - declare module.exports: any; -} - -declare module 'sshpk/lib/identity' { - declare module.exports: any; -} - -declare module 'sshpk/lib/index' { - declare module.exports: any; -} - -declare module 'sshpk/lib/key' { - declare module.exports: any; -} - -declare module 'sshpk/lib/private-key' { - declare module.exports: any; -} - -declare module 'sshpk/lib/signature' { - declare module.exports: any; -} - -declare module 'sshpk/lib/ssh-buffer' { - declare module.exports: any; -} - -declare module 'sshpk/lib/utils' { - declare module.exports: any; -} - -// Filename aliases -declare module 'sshpk/lib/algs.js' { - declare module.exports: $Exports<'sshpk/lib/algs'>; -} -declare module 'sshpk/lib/certificate.js' { - declare module.exports: $Exports<'sshpk/lib/certificate'>; -} -declare module 'sshpk/lib/dhe.js' { - declare module.exports: $Exports<'sshpk/lib/dhe'>; -} -declare module 'sshpk/lib/ed-compat.js' { - declare module.exports: $Exports<'sshpk/lib/ed-compat'>; -} -declare module 'sshpk/lib/errors.js' { - declare module.exports: $Exports<'sshpk/lib/errors'>; -} -declare module 'sshpk/lib/fingerprint.js' { - declare module.exports: $Exports<'sshpk/lib/fingerprint'>; -} -declare module 'sshpk/lib/formats/auto.js' { - declare module.exports: $Exports<'sshpk/lib/formats/auto'>; -} -declare module 'sshpk/lib/formats/openssh-cert.js' { - declare module.exports: $Exports<'sshpk/lib/formats/openssh-cert'>; -} -declare module 'sshpk/lib/formats/pem.js' { - declare module.exports: $Exports<'sshpk/lib/formats/pem'>; -} -declare module 'sshpk/lib/formats/pkcs1.js' { - declare module.exports: $Exports<'sshpk/lib/formats/pkcs1'>; -} -declare module 'sshpk/lib/formats/pkcs8.js' { - declare module.exports: $Exports<'sshpk/lib/formats/pkcs8'>; -} -declare module 'sshpk/lib/formats/rfc4253.js' { - declare module.exports: $Exports<'sshpk/lib/formats/rfc4253'>; -} -declare module 'sshpk/lib/formats/ssh-private.js' { - declare module.exports: $Exports<'sshpk/lib/formats/ssh-private'>; -} -declare module 'sshpk/lib/formats/ssh.js' { - declare module.exports: $Exports<'sshpk/lib/formats/ssh'>; -} -declare module 'sshpk/lib/formats/x509-pem.js' { - declare module.exports: $Exports<'sshpk/lib/formats/x509-pem'>; -} -declare module 'sshpk/lib/formats/x509.js' { - declare module.exports: $Exports<'sshpk/lib/formats/x509'>; -} -declare module 'sshpk/lib/identity.js' { - declare module.exports: $Exports<'sshpk/lib/identity'>; -} -declare module 'sshpk/lib/index.js' { - declare module.exports: $Exports<'sshpk/lib/index'>; -} -declare module 'sshpk/lib/key.js' { - declare module.exports: $Exports<'sshpk/lib/key'>; -} -declare module 'sshpk/lib/private-key.js' { - declare module.exports: $Exports<'sshpk/lib/private-key'>; -} -declare module 'sshpk/lib/signature.js' { - declare module.exports: $Exports<'sshpk/lib/signature'>; -} -declare module 'sshpk/lib/ssh-buffer.js' { - declare module.exports: $Exports<'sshpk/lib/ssh-buffer'>; -} -declare module 'sshpk/lib/utils.js' { - declare module.exports: $Exports<'sshpk/lib/utils'>; -} diff --git a/flow-typed/npm/table_vx.x.x.js b/flow-typed/npm/table_vx.x.x.js deleted file mode 100644 index fd80bf80e..000000000 --- a/flow-typed/npm/table_vx.x.x.js +++ /dev/null @@ -1,389 +0,0 @@ -// flow-typed signature: 9fc47f9afb07f70bb687d0302bc97c59 -// flow-typed version: <>/table_v^4.0.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'table' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'table' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'table/dist/alignString' { - declare module.exports: any; -} - -declare module 'table/dist/alignTableData' { - declare module.exports: any; -} - -declare module 'table/dist/calculateCellHeight' { - declare module.exports: any; -} - -declare module 'table/dist/calculateCellWidthIndex' { - declare module.exports: any; -} - -declare module 'table/dist/calculateMaximumColumnWidthIndex' { - declare module.exports: any; -} - -declare module 'table/dist/calculateRowHeightIndex' { - declare module.exports: any; -} - -declare module 'table/dist/createStream' { - declare module.exports: any; -} - -declare module 'table/dist/drawBorder' { - declare module.exports: any; -} - -declare module 'table/dist/drawRow' { - declare module.exports: any; -} - -declare module 'table/dist/drawTable' { - declare module.exports: any; -} - -declare module 'table/dist/getBorderCharacters' { - declare module.exports: any; -} - -declare module 'table/dist/index' { - declare module.exports: any; -} - -declare module 'table/dist/makeConfig' { - declare module.exports: any; -} - -declare module 'table/dist/makeStreamConfig' { - declare module.exports: any; -} - -declare module 'table/dist/mapDataUsingRowHeightIndex' { - declare module.exports: any; -} - -declare module 'table/dist/padTableData' { - declare module.exports: any; -} - -declare module 'table/dist/stringifyTableData' { - declare module.exports: any; -} - -declare module 'table/dist/table' { - declare module.exports: any; -} - -declare module 'table/dist/truncateTableData' { - declare module.exports: any; -} - -declare module 'table/dist/validateConfig' { - declare module.exports: any; -} - -declare module 'table/dist/validateStreamConfig' { - declare module.exports: any; -} - -declare module 'table/dist/validateTableData' { - declare module.exports: any; -} - -declare module 'table/dist/wrapString' { - declare module.exports: any; -} - -declare module 'table/dist/wrapWord' { - declare module.exports: any; -} - -declare module 'table/test/alignString' { - declare module.exports: any; -} - -declare module 'table/test/calculateCellHeight' { - declare module.exports: any; -} - -declare module 'table/test/calculateCellWidthIndex' { - declare module.exports: any; -} - -declare module 'table/test/calculateMaximumColumnWidthIndex' { - declare module.exports: any; -} - -declare module 'table/test/calculateRowHeightIndex' { - declare module.exports: any; -} - -declare module 'table/test/config' { - declare module.exports: any; -} - -declare module 'table/test/configSamples' { - declare module.exports: any; -} - -declare module 'table/test/createStream' { - declare module.exports: any; -} - -declare module 'table/test/drawBorder' { - declare module.exports: any; -} - -declare module 'table/test/makeConfig' { - declare module.exports: any; -} - -declare module 'table/test/mapDataUsingRowHeightIndex' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/basic' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/cell_content_alignment' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/column_width' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/custom_border' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/draw_horizontal_line' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/expectTable' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/moon_mission' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/padding_cell_content' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/predefined_border_templates' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/streaming' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/text_truncating' { - declare module.exports: any; -} - -declare module 'table/test/README/usage/text_wrapping' { - declare module.exports: any; -} - -declare module 'table/test/streamConfig' { - declare module.exports: any; -} - -declare module 'table/test/streamConfigSamples' { - declare module.exports: any; -} - -declare module 'table/test/validateTableData' { - declare module.exports: any; -} - -declare module 'table/test/wrapString' { - declare module.exports: any; -} - -declare module 'table/test/wrapWord' { - declare module.exports: any; -} - -// Filename aliases -declare module 'table/dist/alignString.js' { - declare module.exports: $Exports<'table/dist/alignString'>; -} -declare module 'table/dist/alignTableData.js' { - declare module.exports: $Exports<'table/dist/alignTableData'>; -} -declare module 'table/dist/calculateCellHeight.js' { - declare module.exports: $Exports<'table/dist/calculateCellHeight'>; -} -declare module 'table/dist/calculateCellWidthIndex.js' { - declare module.exports: $Exports<'table/dist/calculateCellWidthIndex'>; -} -declare module 'table/dist/calculateMaximumColumnWidthIndex.js' { - declare module.exports: $Exports<'table/dist/calculateMaximumColumnWidthIndex'>; -} -declare module 'table/dist/calculateRowHeightIndex.js' { - declare module.exports: $Exports<'table/dist/calculateRowHeightIndex'>; -} -declare module 'table/dist/createStream.js' { - declare module.exports: $Exports<'table/dist/createStream'>; -} -declare module 'table/dist/drawBorder.js' { - declare module.exports: $Exports<'table/dist/drawBorder'>; -} -declare module 'table/dist/drawRow.js' { - declare module.exports: $Exports<'table/dist/drawRow'>; -} -declare module 'table/dist/drawTable.js' { - declare module.exports: $Exports<'table/dist/drawTable'>; -} -declare module 'table/dist/getBorderCharacters.js' { - declare module.exports: $Exports<'table/dist/getBorderCharacters'>; -} -declare module 'table/dist/index.js' { - declare module.exports: $Exports<'table/dist/index'>; -} -declare module 'table/dist/makeConfig.js' { - declare module.exports: $Exports<'table/dist/makeConfig'>; -} -declare module 'table/dist/makeStreamConfig.js' { - declare module.exports: $Exports<'table/dist/makeStreamConfig'>; -} -declare module 'table/dist/mapDataUsingRowHeightIndex.js' { - declare module.exports: $Exports<'table/dist/mapDataUsingRowHeightIndex'>; -} -declare module 'table/dist/padTableData.js' { - declare module.exports: $Exports<'table/dist/padTableData'>; -} -declare module 'table/dist/stringifyTableData.js' { - declare module.exports: $Exports<'table/dist/stringifyTableData'>; -} -declare module 'table/dist/table.js' { - declare module.exports: $Exports<'table/dist/table'>; -} -declare module 'table/dist/truncateTableData.js' { - declare module.exports: $Exports<'table/dist/truncateTableData'>; -} -declare module 'table/dist/validateConfig.js' { - declare module.exports: $Exports<'table/dist/validateConfig'>; -} -declare module 'table/dist/validateStreamConfig.js' { - declare module.exports: $Exports<'table/dist/validateStreamConfig'>; -} -declare module 'table/dist/validateTableData.js' { - declare module.exports: $Exports<'table/dist/validateTableData'>; -} -declare module 'table/dist/wrapString.js' { - declare module.exports: $Exports<'table/dist/wrapString'>; -} -declare module 'table/dist/wrapWord.js' { - declare module.exports: $Exports<'table/dist/wrapWord'>; -} -declare module 'table/test/alignString.js' { - declare module.exports: $Exports<'table/test/alignString'>; -} -declare module 'table/test/calculateCellHeight.js' { - declare module.exports: $Exports<'table/test/calculateCellHeight'>; -} -declare module 'table/test/calculateCellWidthIndex.js' { - declare module.exports: $Exports<'table/test/calculateCellWidthIndex'>; -} -declare module 'table/test/calculateMaximumColumnWidthIndex.js' { - declare module.exports: $Exports<'table/test/calculateMaximumColumnWidthIndex'>; -} -declare module 'table/test/calculateRowHeightIndex.js' { - declare module.exports: $Exports<'table/test/calculateRowHeightIndex'>; -} -declare module 'table/test/config.js' { - declare module.exports: $Exports<'table/test/config'>; -} -declare module 'table/test/configSamples.js' { - declare module.exports: $Exports<'table/test/configSamples'>; -} -declare module 'table/test/createStream.js' { - declare module.exports: $Exports<'table/test/createStream'>; -} -declare module 'table/test/drawBorder.js' { - declare module.exports: $Exports<'table/test/drawBorder'>; -} -declare module 'table/test/makeConfig.js' { - declare module.exports: $Exports<'table/test/makeConfig'>; -} -declare module 'table/test/mapDataUsingRowHeightIndex.js' { - declare module.exports: $Exports<'table/test/mapDataUsingRowHeightIndex'>; -} -declare module 'table/test/README/usage/basic.js' { - declare module.exports: $Exports<'table/test/README/usage/basic'>; -} -declare module 'table/test/README/usage/cell_content_alignment.js' { - declare module.exports: $Exports<'table/test/README/usage/cell_content_alignment'>; -} -declare module 'table/test/README/usage/column_width.js' { - declare module.exports: $Exports<'table/test/README/usage/column_width'>; -} -declare module 'table/test/README/usage/custom_border.js' { - declare module.exports: $Exports<'table/test/README/usage/custom_border'>; -} -declare module 'table/test/README/usage/draw_horizontal_line.js' { - declare module.exports: $Exports<'table/test/README/usage/draw_horizontal_line'>; -} -declare module 'table/test/README/usage/expectTable.js' { - declare module.exports: $Exports<'table/test/README/usage/expectTable'>; -} -declare module 'table/test/README/usage/moon_mission.js' { - declare module.exports: $Exports<'table/test/README/usage/moon_mission'>; -} -declare module 'table/test/README/usage/padding_cell_content.js' { - declare module.exports: $Exports<'table/test/README/usage/padding_cell_content'>; -} -declare module 'table/test/README/usage/predefined_border_templates.js' { - declare module.exports: $Exports<'table/test/README/usage/predefined_border_templates'>; -} -declare module 'table/test/README/usage/streaming.js' { - declare module.exports: $Exports<'table/test/README/usage/streaming'>; -} -declare module 'table/test/README/usage/text_truncating.js' { - declare module.exports: $Exports<'table/test/README/usage/text_truncating'>; -} -declare module 'table/test/README/usage/text_wrapping.js' { - declare module.exports: $Exports<'table/test/README/usage/text_wrapping'>; -} -declare module 'table/test/streamConfig.js' { - declare module.exports: $Exports<'table/test/streamConfig'>; -} -declare module 'table/test/streamConfigSamples.js' { - declare module.exports: $Exports<'table/test/streamConfigSamples'>; -} -declare module 'table/test/validateTableData.js' { - declare module.exports: $Exports<'table/test/validateTableData'>; -} -declare module 'table/test/wrapString.js' { - declare module.exports: $Exports<'table/test/wrapString'>; -} -declare module 'table/test/wrapWord.js' { - declare module.exports: $Exports<'table/test/wrapWord'>; -} diff --git a/flow-typed/npm/winston_vx.x.x.js b/flow-typed/npm/winston_vx.x.x.js deleted file mode 100644 index 2ff6bddca..000000000 --- a/flow-typed/npm/winston_vx.x.x.js +++ /dev/null @@ -1,214 +0,0 @@ -// flow-typed signature: b803cfa42ff085759d495b6b2098a4ae -// flow-typed version: <>/winston_v2.3.1/flow_v0.48.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'winston' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'winston' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'winston/lib/winston' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/common' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/config' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/config/cli-config' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/config/npm-config' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/config/syslog-config' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/container' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/exception' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/logger' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports/console' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports/file' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports/http' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports/memory' { - declare module.exports: any; -} - -declare module 'winston/lib/winston/transports/transport' { - declare module.exports: any; -} - -declare module 'winston/test/helpers' { - declare module.exports: any; -} - -declare module 'winston/test/transports/console-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-archive-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-maxfiles-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-maxsize-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-open-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-stress-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-tailrolling-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/file-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/http-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/memory-test' { - declare module.exports: any; -} - -declare module 'winston/test/transports/transport' { - declare module.exports: any; -} - -// Filename aliases -declare module 'winston/lib/winston.js' { - declare module.exports: $Exports<'winston/lib/winston'>; -} -declare module 'winston/lib/winston/common.js' { - declare module.exports: $Exports<'winston/lib/winston/common'>; -} -declare module 'winston/lib/winston/config.js' { - declare module.exports: $Exports<'winston/lib/winston/config'>; -} -declare module 'winston/lib/winston/config/cli-config.js' { - declare module.exports: $Exports<'winston/lib/winston/config/cli-config'>; -} -declare module 'winston/lib/winston/config/npm-config.js' { - declare module.exports: $Exports<'winston/lib/winston/config/npm-config'>; -} -declare module 'winston/lib/winston/config/syslog-config.js' { - declare module.exports: $Exports<'winston/lib/winston/config/syslog-config'>; -} -declare module 'winston/lib/winston/container.js' { - declare module.exports: $Exports<'winston/lib/winston/container'>; -} -declare module 'winston/lib/winston/exception.js' { - declare module.exports: $Exports<'winston/lib/winston/exception'>; -} -declare module 'winston/lib/winston/logger.js' { - declare module.exports: $Exports<'winston/lib/winston/logger'>; -} -declare module 'winston/lib/winston/transports.js' { - declare module.exports: $Exports<'winston/lib/winston/transports'>; -} -declare module 'winston/lib/winston/transports/console.js' { - declare module.exports: $Exports<'winston/lib/winston/transports/console'>; -} -declare module 'winston/lib/winston/transports/file.js' { - declare module.exports: $Exports<'winston/lib/winston/transports/file'>; -} -declare module 'winston/lib/winston/transports/http.js' { - declare module.exports: $Exports<'winston/lib/winston/transports/http'>; -} -declare module 'winston/lib/winston/transports/memory.js' { - declare module.exports: $Exports<'winston/lib/winston/transports/memory'>; -} -declare module 'winston/lib/winston/transports/transport.js' { - declare module.exports: $Exports<'winston/lib/winston/transports/transport'>; -} -declare module 'winston/test/helpers.js' { - declare module.exports: $Exports<'winston/test/helpers'>; -} -declare module 'winston/test/transports/console-test.js' { - declare module.exports: $Exports<'winston/test/transports/console-test'>; -} -declare module 'winston/test/transports/file-archive-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-archive-test'>; -} -declare module 'winston/test/transports/file-maxfiles-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-maxfiles-test'>; -} -declare module 'winston/test/transports/file-maxsize-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-maxsize-test'>; -} -declare module 'winston/test/transports/file-open-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-open-test'>; -} -declare module 'winston/test/transports/file-stress-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-stress-test'>; -} -declare module 'winston/test/transports/file-tailrolling-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-tailrolling-test'>; -} -declare module 'winston/test/transports/file-test.js' { - declare module.exports: $Exports<'winston/test/transports/file-test'>; -} -declare module 'winston/test/transports/http-test.js' { - declare module.exports: $Exports<'winston/test/transports/http-test'>; -} -declare module 'winston/test/transports/memory-test.js' { - declare module.exports: $Exports<'winston/test/transports/memory-test'>; -} -declare module 'winston/test/transports/transport.js' { - declare module.exports: $Exports<'winston/test/transports/transport'>; -} diff --git a/helpers/annotate-pvc-backup.sh b/helpers/annotate-pvc-backup.sh deleted file mode 100644 index 1b5dd0406..000000000 --- a/helpers/annotate-pvc-backup.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -## -## This annotates all PVCs with the name `solr` and `nginx` with appuio.ch/backup="true" in order that the restic backup system will back them up -## - -oc get pvc --all-namespaces | grep solr | sed '1d' | awk '{ print $2, "--namespace", $1 }' | while read line; do oc annotate --overwrite pvc $line appuio.ch/backup="true"; done -oc get pvc --all-namespaces | grep nginx | sed '1d' | awk '{ print $2, "--namespace", $1 }' | while read line; do oc annotate --overwrite pvc $line appuio.ch/backup="true"; done - -oc get --all-namespaces pod -l 'service in (cli)' | sed '1d' | awk '{ print "--namespace", $1, "pod", $2 }' | while read line; do oc annotate $line --overwrite appuio.ch/backupcommand='/bin/sh -c "if [[ $MARIADB_HOST ]]; then dump=$(mktemp) && mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -h $MARIADB_HOST -u $MARIADB_USERNAME -p$MARIADB_PASSWORD $MARIADB_DATABASE > $dump && cat $dump && rm $dump; fi"'; done \ No newline at end of file diff --git a/helpers/k8up-initiate.sh b/helpers/k8up-initiate.sh deleted file mode 100755 index 9939931f1..000000000 --- a/helpers/k8up-initiate.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/bash - -function outputToYaml() { - IFS='' - while read data; do - echo "$data" >> /tmp/k8up-initiate.yml; - done; -} - -if [ -z "$JWTSECRET" ]; then - echo "JWTSECRET not set" - exit 1 -fi - -if [ -z "$OPENSHIFT_PROJECT" ]; then - echo "OPENSHIFT_PROJECT not set" - exit 1 -fi - -set -eu -o pipefail - -OC="oc" - -echo "${OPENSHIFT_PROJECT}: starting ==================================================================" - -# Fill environment variables which are needed by exec-openshift-resources.sh and the lagoon templates -CONFIGMAP=$($OC -n $OPENSHIFT_PROJECT get configmap lagoon-env -o json) -PROJECT=$(echo "$CONFIGMAP" | jq -r '.data.LAGOON_PROJECT') -SAFE_PROJECT=$(echo "$CONFIGMAP" | jq -r '.data.LAGOON_SAFE_PROJECT') -BRANCH=$(echo "$CONFIGMAP" | jq -r '.data.LAGOON_GIT_BRANCH') -SAFE_BRANCH=$(echo "$CONFIGMAP" | jq -r '.data.LAGOON_GIT_SAFE_BRANCH') -LAGOON_GIT_SHA="00000000000000000000000000000000000000000" -OPENSHIFT_REGISTRY="docker-registry.default.svc:5000" -ROUTER_URL="" -SERVICE_NAME="none" - -PROJECT_SECRET=$(echo -n "$PROJECT-$JWTSECRET" | sha256sum | cut -d " " -f 1) - -# If restic backups are supported by this cluster we create the schedule definition -if oc get customresourcedefinition schedules.backup.appuio.ch > /dev/null; then - - baas_repo_pw=$(oc -n ${OPENSHIFT_PROJECT} create secret generic baas-repo-pw --from-literal=repo-pw=$(echo -n "$PROJECT_SECRET-BAAS-REPO-PW" | sha256sum | cut -d " " -f 1) -o json --dry-run) - - if ! oc -n ${OPENSHIFT_PROJECT} get secret baas-repo-pw &> /dev/null; then - # Create baas-repo-pw secret based on the project secret - echo "$baas_repo_pw" | oc -n ${OPENSHIFT_PROJECT} create -f - - else - echo "$baas_repo_pw" | oc -n ${OPENSHIFT_PROJECT} replace -f - - fi - - TEMPLATE_PARAMETERS=() - - # Run Backups every day at 2200-0200 - BACKUP_SCHEDULE=$( $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/convert-crontab.sh "${OPENSHIFT_PROJECT}" "M H(22-2) * * *") - TEMPLATE_PARAMETERS+=(-p BACKUP_SCHEDULE="${BACKUP_SCHEDULE}") - - # Run Checks on Sunday at 0300-0600 - CHECK_SCHEDULE=$( $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/convert-crontab.sh "${OPENSHIFT_PROJECT}" "M H(3-6) * * 0") - TEMPLATE_PARAMETERS+=(-p CHECK_SCHEDULE="${CHECK_SCHEDULE}") - - # Run Prune on Saturday at 0300-0600 - PRUNE_SCHEDULE=$( $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/convert-crontab.sh "${OPENSHIFT_PROJECT}" "M H(3-6) * * 6") - TEMPLATE_PARAMETERS+=(-p PRUNE_SCHEDULE="${PRUNE_SCHEDULE}") - - OPENSHIFT_TEMPLATE="$(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/openshift-templates/backup/schedule.yml" - . $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/exec-openshift-resources.sh - - oc apply -n ${OPENSHIFT_PROJECT} -f /tmp/k8up-initiate.yml - rm /tmp/k8up-initiate.yml -else - echo "k8sup is not supported by this cluster" - exit 1 -fi - -# Disable backup of solr pvc's -if solr=$(oc -n ${OPENSHIFT_PROJECT} get pvc solr -o json 2> /dev/null) && [[ $(echo "$solr" | jq -r '.metadata.annotations."appuio.ch/backup"') != "false" ]]; then - oc -n ${OPENSHIFT_PROJECT} annotate --overwrite pvc solr appuio.ch/backup="false"; -fi - -# Enable backup of nginx pvc's -if nginx=$(oc -n ${OPENSHIFT_PROJECT} get pvc nginx -o json 2> /dev/null) && [[ $(echo "$nginx" | jq -r '.metadata.annotations."appuio.ch/backup"') != "true" ]]; then - oc -n ${OPENSHIFT_PROJECT} annotate --overwrite pvc nginx appuio.ch/backup="true"; -fi - -# Remove any backupcommand from nginx pods if they exit -if oc -n ${OPENSHIFT_PROJECT} get deploymentconfig nginx -o json 2> /dev/null | jq -r -e '.spec.template.metadata.annotations."appuio.ch/backupcommand"' &> /dev/null; then - oc -n ${OPENSHIFT_PROJECT} patch deploymentconfig nginx --type json -p='[{"op": "remove", "path": "/spec/template/metadata/annotations/appuio.ch~1backupcommand"}]' -fi - -# add backupcommand to clis to backup mariadb -if oc -n ${OPENSHIFT_PROJECT} get deploymentconfig cli &> /dev/null; then - oc -n ${OPENSHIFT_PROJECT} patch deploymentconfig cli -p '{"spec":{"template":{"metadata":{"annotations":{"appuio.ch/backupcommand":"/bin/sh -c \"if [[ $MARIADB_HOST ]]; then dump=$(mktemp) && mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -h $MARIADB_HOST -u $MARIADB_USERNAME -p$MARIADB_PASSWORD $MARIADB_DATABASE > $dump && cat $dump && rm $dump; fi\"", "backup.appuio.ch/file-extension": ".mysql.sql"}}}}}' || true -fi - -echo "${OPENSHIFT_PROJECT}: done ==================================================================" diff --git a/helpers/mariadb-galera2shared.sh b/helpers/mariadb-galera2shared.sh deleted file mode 100755 index fffab3c70..000000000 --- a/helpers/mariadb-galera2shared.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash - - - -if [ ! "$1" ]; then - echo "please define openshift project as first argument" - exit 1; -fi - -set -uo pipefail - -which shyaml > /dev/null -if [ $? -gt 0 ]; then - echo "please install shyaml (pip3 install shyaml)" - exit 1 -fi - -which jq > /dev/null -if [ $? -gt 0 ]; then - echo "please install jq" - exit 1 -fi - -which svcat > /dev/null -if [ $? -gt 0 ]; then - echo "please install svcat" - exit 1 -fi - -set -e - -PROJECT_NAME=$1 - -echo "*** Starting mariadb-galera --> mariadb-shared migration in ${PROJECT_NAME}" - -SERVICE_NAME=mariadb -SERVICE_NAME_UPPERCASE=$(echo $SERVICE_NAME | tr [:lower:] [:upper:]) -SERVICE_TYPE=mariadb-shared - -ENVIRONMENT_TYPE=$(oc -n $1 get configmap lagoon-env -o json | jq -r '.data.LAGOON_ENVIRONMENT_TYPE') - -OLD_POD="mariadb-galera-0" - -if [[ "$OLD_POD" ]]; then - echo "found $SERVICE_NAME pod $OLD_POD" -else - echo "no running pod found for service '${SERVICE_NAME}'', is it running?" - exit 1 -fi - -echo "*** Pausing nginx and cli" -NGINX_REPLICAS=$(oc -n $1 get dc/nginx -o json | jq -r '.spec.replicas') -CLI_REPLICAS=$(oc -n $1 get dc/cli -o json | jq -r '.spec.replicas') -oc -n $1 scale dc/nginx --replicas=0 -oc -n $1 scale dc/cli --replicas=0 - - -# create service broker -## taken from build-deploy-docker-compose.sh - -OPENSHIFT_TEMPLATE="$(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/openshift-templates/${SERVICE_TYPE}/servicebroker.yml" -SERVICEBROKER_CLASS="lagoon-dbaas-mariadb-apb" -SERVICEBROKER_PLAN="${ENVIRONMENT_TYPE}" -OPENSHIFT_PROJECT=$1 -. $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/exec-openshift-create-servicebroker.sh - -# ServiceBrokers take a bit, wait until the credentials secret is available -until oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -do - echo "Secret ${SERVICE_NAME}-servicebroker-credentials not available yet, waiting for 10 secs" - sleep 10 -done - -# Load credentials out of secret -SECRETS=/tmp/${PROJECT_NAME}-${OLD_POD}-migration.yaml -oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -o yaml > $SECRETS - -DB_HOST=$(cat $SECRETS | shyaml get-value data.DB_HOST | base64 -D) -DB_USER=$(cat $SECRETS | shyaml get-value data.DB_USER | base64 -D) -DB_PASSWORD=$(cat $SECRETS | shyaml get-value data.DB_PASSWORD | base64 -D) -DB_NAME=$(cat $SECRETS | shyaml get-value data.DB_NAME | base64 -D) -DB_PORT=$(cat $SECRETS | shyaml get-value data.DB_PORT | base64 -D) - -echo "*** Transfering 'drupal' database from $OLD_POD to $DB_HOST" -# transfer database between from old to new -oc -n $1 exec $OLD_POD -- bash -eo pipefail -c "{ mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db drupal || mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -S /tmp/mysql.sock -u \$MYSQL_USER -p\$MYSQL_PASSWORD \$MYSQL_DATABASE; } | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | mysql -h $DB_HOST -u $DB_USER -p${DB_PASSWORD} -P $DB_PORT $DB_NAME" - -CONFIG_BAK="/tmp/${PROJECT_NAME}-$(date +%F-%T)-lagoon-env.yaml" -echo "*** Backing up configmap in case we need to revert: ${CONFIG_BAK}" -oc -n $1 get configmap lagoon-env -o yaml > $CONFIG_BAK - -echo "*** updating configmap to point to ${DB_HOST}." -# Add credentials to our configmap, prefixed with the name of the servicename of this servicebroker -oc -n $1 patch --insecure-skip-tls-verify configmap lagoon-env \ - -p "{\"data\":{\"${SERVICE_NAME_UPPERCASE}_HOST\":\"${DB_HOST}\", \"${SERVICE_NAME_UPPERCASE}_USERNAME\":\"${DB_USER}\", \"${SERVICE_NAME_UPPERCASE}_PASSWORD\":\"${DB_PASSWORD}\", \"${SERVICE_NAME_UPPERCASE}_DATABASE\":\"${DB_NAME}\", \"${SERVICE_NAME_UPPERCASE}_PORT\":\"${DB_PORT}\"}}" - - -echo "*** Deleting mariadb service. Scaling old mariadb to 0; you can clean up the DC and pv later" -oc -n $1 delete service mariadb -oc -n $1 scale dc/mariadb-maxscale --replicas=0 -oc -n $1 scale statefulset/mariadb-galera --replicas=0 - - -# transfer complete, clean up -rm -f $SECRETS - -oc -n $1 scale dc/nginx --replicas=$NGINX_REPLICAS -oc -n $1 scale dc/cli --replicas=$CLI_REPLICAS - -oc -n $1 rollout latest dc/nginx -oc -n $1 rollout latest dc/cli -oc -n $1 rollout status dc/nginx -oc -n $1 rollout status dc/cli -echo "*** done." diff --git a/helpers/mariadb-single2shared-no-nginx.sh b/helpers/mariadb-single2shared-no-nginx.sh deleted file mode 100755 index 8b59b98a6..000000000 --- a/helpers/mariadb-single2shared-no-nginx.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash - - - -if [ ! "$1" ]; then - echo "please define openshift project as first argument" - exit 1; -fi - -set -uo pipefail - -which shyaml > /dev/null -if [ $? -gt 0 ]; then - echo "please install shyaml (pip3 install shyaml)" - exit 1 -fi - -which jq > /dev/null -if [ $? -gt 0 ]; then - echo "please install jq" - exit 1 -fi - -which svcat > /dev/null -if [ $? -gt 0 ]; then - echo "please install svcat" - exit 1 -fi - -set -e - -PROJECT_NAME=$1 - -echo "*** Starting mariadb-single --> mariadb-shared migration in ${PROJECT_NAME}" - -SERVICE_NAME=mariadb -SERVICE_NAME_UPPERCASE=$(echo $SERVICE_NAME | tr [:lower:] [:upper:]) -SERVICE_TYPE=mariadb-shared - -ENVIRONMENT_TYPE=$(oc -n $1 get configmap lagoon-env -o json | jq -r '.data.LAGOON_ENVIRONMENT_TYPE') - -MARIADB_REPLICAS=$(oc -n $1 get dc/mariadb -o json | jq -r '.spec.replicas') - -if [ "$MARIADB_REPLICAS" == "0" ]; then - oc -n $1 scale dc/mariadb --replicas=1 - oc -n $1 rollout status dc/mariadb -fi - -# export old mariadb pod name -OLD_POD=$(oc -n $1 get pod -o custom-columns=NAME:.metadata.name --no-headers -l service=$SERVICE_NAME) - -if [[ "$OLD_POD" ]]; then - echo "found $SERVICE_NAME pod $OLD_POD" -else - echo "no running pod found for service '${SERVICE_NAME}'', is it running?" - exit 1 -fi - -# create service broker -## taken from build-deploy-docker-compose.sh - -OPENSHIFT_TEMPLATE="$(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/openshift-templates/${SERVICE_TYPE}/servicebroker.yml" -SERVICEBROKER_CLASS="lagoon-dbaas-mariadb-apb" -SERVICEBROKER_PLAN="${ENVIRONMENT_TYPE}" -OPENSHIFT_PROJECT=$1 -. $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/exec-openshift-create-servicebroker.sh - -# ServiceBrokers take a bit, wait until the credentials secret is available -until oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -do - echo "Secret ${SERVICE_NAME}-servicebroker-credentials not available yet, waiting for 10 secs" - sleep 10 -done - -# Load credentials out of secret -SECRETS=/tmp/${PROJECT_NAME}-${OLD_POD}-migration.yaml -oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -o yaml > $SECRETS - -DB_HOST=$(cat $SECRETS | shyaml get-value data.DB_HOST | base64 -D) -DB_USER=$(cat $SECRETS | shyaml get-value data.DB_USER | base64 -D) -DB_PASSWORD=$(cat $SECRETS | shyaml get-value data.DB_PASSWORD | base64 -D) -DB_NAME=$(cat $SECRETS | shyaml get-value data.DB_NAME | base64 -D) -DB_PORT=$(cat $SECRETS | shyaml get-value data.DB_PORT | base64 -D) - -echo "*** Transfering 'drupal' database from $OLD_POD to $DB_HOST" -# transfer database between from old to new -oc -n $1 exec $OLD_POD -- bash -eo pipefail -c "{ mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db \$MARIADB_DATABASE || mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -S /tmp/mysql.sock -u \$MYSQL_USER -p\$MYSQL_PASSWORD \$MYSQL_DATABASE; } | mysql -h $DB_HOST -u $DB_USER -p${DB_PASSWORD} -P $DB_PORT $DB_NAME" - -CONFIG_BAK="/tmp/${PROJECT_NAME}-$(date +%F-%T)-lagoon-env.yaml" -echo "*** Backing up configmap in case we need to revert: ${CONFIG_BAK}" -oc -n $1 get configmap lagoon-env -o yaml > $CONFIG_BAK - -echo "*** updating configmap to point to ${DB_HOST}." -# Add credentials to our configmap, prefixed with the name of the servicename of this servicebroker -oc -n $1 patch --insecure-skip-tls-verify configmap lagoon-env \ - -p "{\"data\":{\"${SERVICE_NAME_UPPERCASE}_HOST\":\"${DB_HOST}\", \"${SERVICE_NAME_UPPERCASE}_USERNAME\":\"${DB_USER}\", \"${SERVICE_NAME_UPPERCASE}_PASSWORD\":\"${DB_PASSWORD}\", \"${SERVICE_NAME_UPPERCASE}_DATABASE\":\"${DB_NAME}\", \"${SERVICE_NAME_UPPERCASE}_PORT\":\"${DB_PORT}\"}}" - - -echo "*** Deleting mariadb service. Scaling old mariadb to 0; you can clean up the DC and pv later" -oc -n $1 delete service mariadb -oc -n $1 scale dc/mariadb --replicas=0 - -# transfer complete, clean up -rm -f $SECRETS - -echo "*** done." diff --git a/helpers/mariadb-single2shared-wordpress.sh b/helpers/mariadb-single2shared-wordpress.sh deleted file mode 100755 index 13461cfbf..000000000 --- a/helpers/mariadb-single2shared-wordpress.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash - - - -if [ ! "$1" ]; then - echo "please define openshift project as first argument" - exit 1; -fi - -set -uo pipefail - -which shyaml > /dev/null -if [ $? -gt 0 ]; then - echo "please install shyaml (pip3 install shyaml)" - exit 1 -fi - -which jq > /dev/null -if [ $? -gt 0 ]; then - echo "please install jq" - exit 1 -fi - -which svcat > /dev/null -if [ $? -gt 0 ]; then - echo "please install svcat" - exit 1 -fi - -set -e - -PROJECT_NAME=$1 - -echo "*** Starting mariadb-single --> mariadb-shared migration in ${PROJECT_NAME}" - -SERVICE_NAME=mariadb -SERVICE_NAME_UPPERCASE=$(echo $SERVICE_NAME | tr [:lower:] [:upper:]) -SERVICE_TYPE=mariadb-shared - -ENVIRONMENT_TYPE=$(oc -n $1 get configmap lagoon-env -o json | jq -r '.data.LAGOON_ENVIRONMENT_TYPE') - -MARIADB_REPLICAS=$(oc -n $1 get dc/mariadb -o json | jq -r '.spec.replicas') - -if [ "$MARIADB_REPLICAS" == "0" ]; then - oc -n $1 scale dc/mariadb --replicas=1 - oc -n $1 rollout status dc/mariadb -fi - -# export old mariadb pod name -OLD_POD=$(oc -n $1 get pod -o custom-columns=NAME:.metadata.name --no-headers -l service=$SERVICE_NAME) - -if [[ "$OLD_POD" ]]; then - echo "found $SERVICE_NAME pod $OLD_POD" -else - echo "no running pod found for service '${SERVICE_NAME}'', is it running?" - exit 1 -fi - -echo "*** Pausing nginx and cli" -NGINX_REPLICAS=$(oc -n $1 get dc/nginx -o json | jq -r '.spec.replicas') -CLI_REPLICAS=$(oc -n $1 get dc/cli -o json | jq -r '.spec.replicas') -oc -n $1 scale dc/nginx --replicas=0 -oc -n $1 scale dc/cli --replicas=0 - - -# create service broker -## taken from build-deploy-docker-compose.sh - -OPENSHIFT_TEMPLATE="$(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/openshift-templates/${SERVICE_TYPE}/servicebroker.yml" -SERVICEBROKER_CLASS="lagoon-dbaas-mariadb-apb" -SERVICEBROKER_PLAN="${ENVIRONMENT_TYPE}" -OPENSHIFT_PROJECT=$1 -. $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/exec-openshift-create-servicebroker.sh - -# ServiceBrokers take a bit, wait until the credentials secret is available -until oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -do - echo "Secret ${SERVICE_NAME}-servicebroker-credentials not available yet, waiting for 10 secs" - sleep 10 -done - -# Load credentials out of secret -SECRETS=/tmp/${PROJECT_NAME}-${OLD_POD}-migration.yaml -oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -o yaml > $SECRETS - -DB_HOST=$(cat $SECRETS | shyaml get-value data.DB_HOST | base64 -D) -DB_USER=$(cat $SECRETS | shyaml get-value data.DB_USER | base64 -D) -DB_PASSWORD=$(cat $SECRETS | shyaml get-value data.DB_PASSWORD | base64 -D) -DB_NAME=$(cat $SECRETS | shyaml get-value data.DB_NAME | base64 -D) -DB_PORT=$(cat $SECRETS | shyaml get-value data.DB_PORT | base64 -D) - -echo "*** Transfering 'drupal' database from $OLD_POD to $DB_HOST" -# transfer database between from old to new -oc -n $1 exec $OLD_POD -- bash -eo pipefail -c "{ mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db lagoon || mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -S /tmp/mysql.sock -u \$MYSQL_USER -p\$MYSQL_PASSWORD \$MYSQL_DATABASE; } | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | mysql -h $DB_HOST -u $DB_USER -p${DB_PASSWORD} -P $DB_PORT $DB_NAME" - -CONFIG_BAK="/tmp/${PROJECT_NAME}-$(date +%F-%T)-lagoon-env.yaml" -echo "*** Backing up configmap in case we need to revert: ${CONFIG_BAK}" -oc -n $1 get configmap lagoon-env -o yaml > $CONFIG_BAK - -echo "*** updating configmap to point to ${DB_HOST}." -# Add credentials to our configmap, prefixed with the name of the servicename of this servicebroker -oc -n $1 patch --insecure-skip-tls-verify configmap lagoon-env \ - -p "{\"data\":{\"${SERVICE_NAME_UPPERCASE}_HOST\":\"${DB_HOST}\", \"${SERVICE_NAME_UPPERCASE}_USERNAME\":\"${DB_USER}\", \"${SERVICE_NAME_UPPERCASE}_PASSWORD\":\"${DB_PASSWORD}\", \"${SERVICE_NAME_UPPERCASE}_DATABASE\":\"${DB_NAME}\", \"${SERVICE_NAME_UPPERCASE}_PORT\":\"${DB_PORT}\"}}" - - -echo "*** Deleting mariadb service. Scaling old mariadb to 0; you can clean up the DC and pv later" -oc -n $1 delete service mariadb -oc -n $1 scale dc/mariadb --replicas=0 - -# transfer complete, clean up -rm -f $SECRETS - -oc -n $1 scale dc/nginx --replicas=$NGINX_REPLICAS -oc -n $1 scale dc/cli --replicas=$CLI_REPLICAS - -oc -n $1 rollout latest dc/nginx -oc -n $1 rollout latest dc/cli -oc -n $1 rollout status dc/nginx -oc -n $1 rollout status dc/cli -echo "*** done." diff --git a/helpers/mariadb-single2shared.sh b/helpers/mariadb-single2shared.sh deleted file mode 100755 index 9a281271b..000000000 --- a/helpers/mariadb-single2shared.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/bash - - - -if [ ! "$1" ]; then - echo "please define openshift project as first argument" - exit 1; -fi - -set -uo pipefail - -which shyaml > /dev/null -if [ $? -gt 0 ]; then - echo "please install shyaml (pip3 install shyaml)" - exit 1 -fi - -which jq > /dev/null -if [ $? -gt 0 ]; then - echo "please install jq" - exit 1 -fi - -which svcat > /dev/null -if [ $? -gt 0 ]; then - echo "please install svcat" - exit 1 -fi - -set -e - -PROJECT_NAME=$1 - -echo "*** Starting mariadb-single --> mariadb-shared migration in ${PROJECT_NAME}" - -SERVICE_NAME=mariadb -SERVICE_NAME_UPPERCASE=$(echo $SERVICE_NAME | tr [:lower:] [:upper:]) -SERVICE_TYPE=mariadb-shared - -ENVIRONMENT_TYPE=$(oc -n $1 get configmap lagoon-env -o json | jq -r '.data.LAGOON_ENVIRONMENT_TYPE') - -MARIADB_REPLICAS=$(oc -n $1 get dc/mariadb -o json | jq -r '.spec.replicas') - -if [ "$MARIADB_REPLICAS" == "0" ]; then - oc -n $1 scale dc/mariadb --replicas=1 - oc -n $1 rollout status dc/mariadb -fi - -# export old mariadb pod name -OLD_POD=$(oc -n $1 get pod -o custom-columns=NAME:.metadata.name --no-headers -l service=$SERVICE_NAME) - -if [[ "$OLD_POD" ]]; then - echo "found $SERVICE_NAME pod $OLD_POD" -else - echo "no running pod found for service '${SERVICE_NAME}'', is it running?" - exit 1 -fi - -echo "*** Pausing nginx and cli" -NGINX_REPLICAS=$(oc -n $1 get dc/nginx -o json | jq -r '.spec.replicas') -CLI_REPLICAS=$(oc -n $1 get dc/cli -o json | jq -r '.spec.replicas') -oc -n $1 scale dc/nginx --replicas=0 -oc -n $1 scale dc/cli --replicas=0 - - -# create service broker -## taken from build-deploy-docker-compose.sh - -OPENSHIFT_TEMPLATE="$(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/openshift-templates/${SERVICE_TYPE}/servicebroker.yml" -SERVICEBROKER_CLASS="lagoon-dbaas-mariadb-apb" -SERVICEBROKER_PLAN="${ENVIRONMENT_TYPE}" -OPENSHIFT_PROJECT=$1 -. $(git rev-parse --show-toplevel)/images/oc-build-deploy-dind/scripts/exec-openshift-create-servicebroker.sh - -# ServiceBrokers take a bit, wait until the credentials secret is available -until oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -do - echo "Secret ${SERVICE_NAME}-servicebroker-credentials not available yet, waiting for 10 secs" - sleep 10 -done - -# Load credentials out of secret -SECRETS=/tmp/${PROJECT_NAME}-${OLD_POD}-migration.yaml -oc -n $1 get --insecure-skip-tls-verify secret ${SERVICE_NAME}-servicebroker-credentials -o yaml > $SECRETS - -DB_HOST=$(cat $SECRETS | shyaml get-value data.DB_HOST | base64 -D) -DB_USER=$(cat $SECRETS | shyaml get-value data.DB_USER | base64 -D) -DB_PASSWORD=$(cat $SECRETS | shyaml get-value data.DB_PASSWORD | base64 -D) -DB_NAME=$(cat $SECRETS | shyaml get-value data.DB_NAME | base64 -D) -DB_PORT=$(cat $SECRETS | shyaml get-value data.DB_PORT | base64 -D) - -echo "*** Transfering 'drupal' database from $OLD_POD to $DB_HOST" -# transfer database between from old to new -oc -n $1 exec $OLD_POD -- bash -eo pipefail -c "{ mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db drupal || mysqldump --max-allowed-packet=500M --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db -S /tmp/mysql.sock -u \$MYSQL_USER -p\$MYSQL_PASSWORD \$MYSQL_DATABASE; } | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | mysql -h $DB_HOST -u $DB_USER -p${DB_PASSWORD} -P $DB_PORT $DB_NAME" - -CONFIG_BAK="/tmp/${PROJECT_NAME}-$(date +%F-%T)-lagoon-env.yaml" -echo "*** Backing up configmap in case we need to revert: ${CONFIG_BAK}" -oc -n $1 get configmap lagoon-env -o yaml > $CONFIG_BAK - -echo "*** updating configmap to point to ${DB_HOST}." -# Add credentials to our configmap, prefixed with the name of the servicename of this servicebroker -oc -n $1 patch --insecure-skip-tls-verify configmap lagoon-env \ - -p "{\"data\":{\"${SERVICE_NAME_UPPERCASE}_HOST\":\"${DB_HOST}\", \"${SERVICE_NAME_UPPERCASE}_USERNAME\":\"${DB_USER}\", \"${SERVICE_NAME_UPPERCASE}_PASSWORD\":\"${DB_PASSWORD}\", \"${SERVICE_NAME_UPPERCASE}_DATABASE\":\"${DB_NAME}\", \"${SERVICE_NAME_UPPERCASE}_PORT\":\"${DB_PORT}\"}}" - - -echo "*** Deleting mariadb service. Scaling old mariadb to 0; you can clean up the DC and pv later" -oc -n $1 delete service mariadb -oc -n $1 scale dc/mariadb --replicas=0 - -# transfer complete, clean up -rm -f $SECRETS - -oc -n $1 scale dc/nginx --replicas=$NGINX_REPLICAS -oc -n $1 scale dc/cli --replicas=$CLI_REPLICAS - -oc -n $1 rollout latest dc/nginx -oc -n $1 rollout latest dc/cli -oc -n $1 rollout status dc/nginx -oc -n $1 rollout status dc/cli -echo "*** done." diff --git a/helpers/reclaim-pv.sh b/helpers/reclaim-pv.sh deleted file mode 100755 index cc80a896c..000000000 --- a/helpers/reclaim-pv.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/bash - -# written for openshift 3.7; small changes may be required for other versions. -# -# usage ./reclaim-pv.sh -# -# using the current openshift server and namepsace this script will: -# 1. scale all deployments to zero pods -# 2. create a pod and attach all temporary pvc. -# 3. attach all other pvcs in the namepace current claims to this pod. -# 4. for each pvc, -# copy the contents to temporary pvc, recreate the claim. -# this allows for the prefered pv to be used -# attach the newly created pvc, copy contents back to it -# 6. clean up - -OC=oc -PVCS=($(${OC} get pvc -o name | sed 's/persistentvolumeclaims\///')) - -if [[ $# -gt 0 ]]; then - unset PVCS - PVCS=("${BASH_ARGV[@]}") -fi - -if [[ ! ${#PVCS[@]} -gt 0 ]]; then - echo "no PVCs found." - -else - ${OC} create serviceaccount pvcreclaim - ${OC} adm policy add-scc-to-user privileged -z pvcreclaim - - ${OC} get dc -o name --no-headers | xargs -P3 -n1 ${OC} scale --replicas=0 - - ${OC} run --image alpine pv-migrator -- sh -c "while sleep 3600; do :; done" - - # change serviceaccount name so i can run as privileged - ${OC} patch deploymentconfig/pv-migrator -p '{"spec":{"template":{"spec":{"serviceAccountName": "pvcreclaim"}}}}' - # now run as root - ${OC} patch deploymentconfig/pv-migrator -p '{"spec":{"template":{"spec":{"securityContext":{ "privileged": "true", "runAsUser": 0 }}}}}' - - ${OC} rollout pause deploymentconfig/pv-migrator - - for PVC in "${PVCS[@]}" - do - echo "adding ${PVC} to pv-migrator." - ${OC} volume deploymentconfig/pv-migrator --add --name=${PVC} --type=persistentVolumeClaim --claim-name=${PVC} --mount-path=/storage/${PVC} - done - -cat << EOF | ${OC} apply -f - - apiVersion: v1 - items: - - apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - name: migrator - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi - kind: List - metadata: {} -EOF - - - ${OC} volume deploymentconfig/pv-migrator --add --name=migrator --type=persistentVolumeClaim --claim-name=migrator --mount-path=/migrator - - ${OC} rollout resume deploymentconfig/pv-migrator - ${OC} rollout status deploymentconfig/pv-migrator --watch - - # - MIGRATOR=$(${OC} get pods -l run=pv-migrator -o json | jq -r '.items[] | select(.metadata.deletionTimestamp == null) | select(.status.phase == "Running") | .metadata.name' | head -n 1) - #MIGRATOR=$(${OC} get pod -o custom-columns=NAME:.metadata.name --no-headers -l run=pv-migrator) - if [[ ! $MIGRATOR ]]; then - echo "No running pod found for migrator" - exit 1 - fi - - for PVC in "${PVCS[@]}" - do - echo "copy ${PVC} to storage" - ${OC} exec $MIGRATOR -- cp -Rpav /storage/${PVC} /migrator/ - - TMP=$(mktemp temp.${PVC}.json.XXXX) - - echo "dumping pvc ${PVC} to ${TMP}." - ${OC} get -o json pvc/${PVC} --export=true | jq 'del(.metadata.annotations, .metadata.selfLink, .spec.volumeName, .spec.storageClassName, .status)' > $TMP - - - ${OC} rollout pause deploymentconfig/pv-migrator - - ${OC} volume deploymentconfig/pv-migrator --remove --name=${PVC} - ${OC} delete pvc/${PVC} - ${OC} create -f $TMP && rm $TMP - ${OC} volume deploymentconfig/pv-migrator --add --name=${PVC} --type=persistentVolumeClaim --claim-name=${PVC} --mount-path=/storage/${PVC} - - ${OC} rollout resume deploymentconfig/pv-migrator - ${OC} rollout status deploymentconfig/pv-migrator --watch - - - MIGRATOR=$(${OC} get pods -l run=pv-migrator -o json | jq -r '.items[] | select(.metadata.deletionTimestamp == null) | select(.status.phase == "Running") | .metadata.name' | head -n 1) - - ${OC} exec $MIGRATOR -- cp -Rpav /migrator/${PVC} /storage/ - ${OC} exec $MIGRATOR -- ls -la /storage/${PVC} - - - - - done - - ${OC} delete deploymentconfig/pv-migrator - ${OC} delete pvc/migrator - ${OC} get dc -o name --no-headers | xargs -P3 -n1 ${OC} scale --replicas=1 - - ${OC} adm policy remove-scc-from-user privileged -z pvcreclaim - ${OC} delete serviceaccount pvcreclaim - -fi diff --git a/helpers/run-in-all-lagoon-projects.sh b/helpers/run-in-all-lagoon-projects.sh deleted file mode 100755 index 55b69daa5..000000000 --- a/helpers/run-in-all-lagoon-projects.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -eu -o pipefail - -OC="oc" - -oc get configmaps --all-namespaces --no-headers | grep lagoon-env | awk '{ print $1 }' | while read OPENSHIFT_PROJECT; do - REGEX=${REGEX:-.*} - if [[ $OPENSHIFT_PROJECT =~ $REGEX ]]; then - . "$1" - fi -done \ No newline at end of file diff --git a/helpers/sharedmigrate.sh b/helpers/sharedmigrate.sh deleted file mode 100755 index 973ea9064..000000000 --- a/helpers/sharedmigrate.sh +++ /dev/null @@ -1,200 +0,0 @@ -#!/bin/sh - -for util in oc svcat jq; do -which ${util} > /dev/null -if [ $? -gt 0 ]; then - echo "please install ${util}" - exit 1 -fi -done; - -usage() { - cat << EOF - ${0}: migrate a mariadb servicebroker to another mariadb servicebroker - This script is useful when needing to change either the class or the plan - of and existing service broker. - By default, it will use: - 'lagoon-dbaas-mariadb-apb' as the class, - 'production' as the plan, - current openshift context as the namespace, and - first servicebroker in the namespace. - - when completed, run with -x to delete migration pvc, dc and serviceaccount. - - e.g: $0 -n mysite-devel -c lagoon-dbaas-mariadb-apb -p development -i mariadb - $0 -n mysite-devel -x -EOF -} - -# n- namespace -# c- class ( lagoon-dbaas-mariadb-apb ) -# p- plan ( production / stage ) - -args=`getopt n:c:p:i:xh $*` -if [[ $# -eq 0 ]]; then - usage - exit -fi - -# set some defaults -NAMESPACE=$(oc project -q) -PLAN=production -CLASS=lagoon-dbaas-mariadb-apb - -set -- $args -for i -do - case "$i" in - -n) - NAMESPACE="$2"; shift; - shift;; - -c) - CLASS="$2"; shift; - shift;; - -p) - PLAN="$2"; shift; - shift;; - -i) - INSTANCE="$2"; shift; - shift;; - -h) - usage - exit 0 - shift;; - - -x) - echo "cleaning up " - oc -n ${NAMESPACE} delete dc/migrator - oc -n ${NAMESPACE} delete pvc/migrator - oc -n ${NAMESPACE} adm policy remove-scc-from-user privileged -z migrator - oc -n ${NAMESPACE} delete serviceaccount migrator - exit 0 - shift;; - - --) - shift; break;; - esac -done - -# set a default instance, if not specified. -if [ -z ${INSTANCE+x} ]; then - INSTANCE=$(svcat -n ${NAMESPACE} get instance -o json |jq -r '.items[0].metadata.name') - echo "instance not specified, using $INSTANCE" -fi - -# verify instance exists -svcat -n ${NAMESPACE} get instance $INSTANCE -if [ $? -gt 0 ] ;then - echo "no instance found" - exit 2 -fi - -echo "Verifying secret ${INSTANCE}-servicebroker-credentials " -oc -n ${NAMESPACE} get --insecure-skip-tls-verify secret ${INSTANCE}-servicebroker-credentials || svcat bind $INSTANCE --name ${INSTANCE}-servicebroker-credentials - -# validate $broker - -oc -n ${NAMESPACE} create serviceaccount migrator -oc -n ${NAMESPACE} adm policy add-scc-to-user privileged -z migrator - -oc -n ${NAMESPACE} run --image mariadb --env="MYSQL_RANDOM_ROOT_PASSWORD=yes" migrator - -# pause and make some changes -oc -n ${NAMESPACE} rollout pause deploymentconfig/migrator - -# We don't care about the database in /var/lib/mysql; just privilege it and let it do its thing. -oc -n ${NAMESPACE} patch deploymentconfig/migrator -p '{"spec":{"template":{"spec":{"serviceAccountName": "migrator"}}}}' -oc -n ${NAMESPACE} patch deploymentconfig/migrator -p '{"spec":{"template":{"spec":{"securityContext":{ "privileged": "true", "runAsUser": 0 }}}}}' -oc -n ${NAMESPACE} patch deploymentconfig/migrator -p '{"spec":{"strategy":{"type":"Recreate"}}}' - - -# create a volume to store the dump. -cat << EOF | oc -n ${NAMESPACE} apply -f - - apiVersion: v1 - items: - - apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - name: migrator - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi - kind: List - metadata: {} -EOF - -oc -n ${NAMESPACE} volume deploymentconfig/migrator --add --name=migrator --type=persistentVolumeClaim --claim-name=migrator --mount-path=/migrator - - -# look up the secret from the instance and add it to the new container -SECRET=$(svcat -n ${NAMESPACE} get binding -o json |jq -r ".items[] | select (.spec.instanceRef.name == \"$INSTANCE\") | .spec.secretName") -echo secret: $SECRET -oc -n ${NAMESPACE} set env --from=secret/${SECRET} --prefix=OLD_ dc/migrator - -oc -n ${NAMESPACE} rollout resume deploymentconfig/migrator -oc -n ${NAMESPACE} rollout latest deploymentconfig/migrator -oc -n ${NAMESPACE} rollout status deploymentconfig/migrator --watch - -sleep 20; -# Do the dump: -POD=$(oc -n ${NAMESPACE} get pods -o json --show-all=false -l run=migrator | jq -r '.items[].metadata.name') - -oc -n ${NAMESPACE} exec $POD -- bash -c 'time mysqldump -h $OLD_DB_HOST -u $OLD_DB_USER -p${OLD_DB_PASSWORD} $OLD_DB_NAME > /migrator/migration.sql' - -echo "DUMP IS DONE;" -oc -n ${NAMESPACE} exec $POD -- ls -al /migrator/migration.sql || exit 1 -oc -n ${NAMESPACE} exec $POD -- head /migrator/migration.sql -oc -n ${NAMESPACE} exec $POD -- tail /migrator/migration.sql || exit 1 - - -printf "\n\n\nLAST CHANCE TO CANCEL BEFORE I DELETE THE OLD SERVICEBROKER.\n\n" -echo "sleeping 30 seconds..." -sleep 30 - -# delete the old servicebroker -time svcat -n ${NAMESPACE} unbind $INSTANCE -time svcat -n ${NAMESPACE} deprovision $INSTANCE --wait --interval 2s --timeout=1h -echo "===== old instance deprovisioned, waiting 30 seconds." -sleep 30; - -echo "===== provisioning new $CLASS of plan $PLAN" -time svcat -n ${NAMESPACE} provision $INSTANCE --class $CLASS --plan $PLAN --wait -echo " and binding" -time svcat -n ${NAMESPACE} bind $INSTANCE --name ${INSTANCE}-servicebroker-credentials --wait - -until oc get -n ${NAMESPACE} secret ${INSTANCE}-servicebroker-credentials -do - echo "Secret ${SERVICE_NAME}-servicebroker-credentials not available yet, waiting for 5 secs" - sleep 5 -done - - -echo "rolling out migrator again so the secrets get propagated." -oc -n ${NAMESPACE} rollout latest deploymentconfig/migrator -oc -n ${NAMESPACE} rollout status deploymentconfig/migrator --watch - -sleep 10; - -# Do the dump: -POD=$(oc -n ${NAMESPACE} get pods -o json --show-all=false -l run=migrator | jq -r '.items[].metadata.name') - -oc -n ${NAMESPACE} exec $POD -- bash -c 'cat /migrator/migration.sql |sed -e "s/DEFINER[ ]*=[ ]*[^*]*\*/\*/" | mysql -h $OLD_DB_HOST -u $OLD_DB_USER -p${OLD_DB_PASSWORD} $OLD_DB_NAME' - - -# Load credentials out of secret -SECRETS=$(mktemp).yaml -echo "Exporting ${INSTANCE}-servicebroker-credentials into $SECRETS " -oc -n ${NAMESPACE} get --insecure-skip-tls-verify secret ${INSTANCE}-servicebroker-credentials -o yaml > $SECRETS - -DB_HOST=$(cat $SECRETS | shyaml get-value data.DB_HOST | base64 -D) -DB_USER=$(cat $SECRETS | shyaml get-value data.DB_USER | base64 -D) -DB_PASSWORD=$(cat $SECRETS | shyaml get-value data.DB_PASSWORD | base64 -D) -DB_NAME=$(cat $SECRETS | shyaml get-value data.DB_NAME | base64 -D) -DB_PORT=$(cat $SECRETS | shyaml get-value data.DB_PORT | base64 -D) - -SERVICE_NAME_UPPERCASE=$(echo $INSTANCE | tr [:lower:] [:upper:]) -oc -n $NAMESPACE patch configmap lagoon-env \ - -p "{\"data\":{\"${SERVICE_NAME_UPPERCASE}_HOST\":\"${DB_HOST}\", \"${SERVICE_NAME_UPPERCASE}_USERNAME\":\"${DB_USER}\", \"${SERVICE_NAME_UPPERCASE}_PASSWORD\":\"${DB_PASSWORD}\", \"${SERVICE_NAME_UPPERCASE}_DATABASE\":\"${DB_NAME}\", \"${SERVICE_NAME_UPPERCASE}_PORT\":\"${DB_PORT}\"}}" diff --git a/images/athenapdf-service/Dockerfile b/images/athenapdf-service/Dockerfile deleted file mode 100644 index b67e1e1d1..000000000 --- a/images/athenapdf-service/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -ARG IMAGE_REPO -FROM ${IMAGE_REPO:-lagoon}/commons as commons -FROM arachnysdocker/athenapdf-service:2.13.0 - -LABEL maintainer="amazee.io" -ENV LAGOON=athenapdf-service - -# Copy commons files -COPY --from=commons /lagoon /lagoon -COPY --from=commons /bin/fix-permissions /bin/ep /bin/docker-sleep /bin/ -COPY --from=commons /home /home - -RUN chmod g+w /etc/passwd \ - && mkdir -p /home - -# Reproduce behavior of Alpine: Run Bash as sh -RUN rm -f /bin/sh && ln -s /bin/bash /bin/sh - -ENV TMPDIR=/tmp \ - TMP=/tmp \ - HOME=/home \ - # When Bash is invoked via `sh` it behaves like the old Bourne Shell and sources a file that is given in `ENV` - ENV=/home/.bashrc \ - # When Bash is invoked as non-interactive (like `bash -c command`) it sources a file that is given in `BASH_ENV` - BASH_ENV=/home/.bashrc - -ENV WEAVER_ATHENA_CMD="athenapdf --no-cache --ignore-certificate-errors -S" -ENV WEAVER_AUTH_KEY=lagoon-athenapdf - -COPY entrypoint.sh /athenapdf-service/conf/entrypoint.sh diff --git a/images/athenapdf-service/entrypoint.sh b/images/athenapdf-service/entrypoint.sh deleted file mode 100755 index f18222be8..000000000 --- a/images/athenapdf-service/entrypoint.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -# Block bad hosts, if /etc/hosts is writeable -if [ -w /etc/hosts ]; then - cat conf/hosts >> /etc/hosts -fi - -rm -f /tmp/.X99-lock -export DISPLAY=:99 - -exec "$@" \ No newline at end of file diff --git a/images/commons/.bashrc b/images/commons/.bashrc deleted file mode 100644 index c5fb3f420..000000000 --- a/images/commons/.bashrc +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh - -# Make sure that new files generated by Docker have group write permission -source /lagoon/entrypoints/00-umask.sh - -# Loading environment variables from .env and friends -source /lagoon/entrypoints/50-dotenv.sh - -# Generate some additional enviornment variables -source /lagoon/entrypoints/55-generate-env.sh - -# a nicer prompt -if [ "$PS1" ]; then - NORMAL="\[\e[0m\]" - RED="\[\e[1;31m\]" - GREEN="\[\e[0;32m\]" - YELLOW="\[\e[1;33m\]" - BLUE="\[\e[1;34m\]" - WHITE="\[\e[1;37m\]" - PS1="${YELLOW}\w${NORMAL}$ " - if [ "$LAGOON" ]; then - PS1="${GREEN}$LAGOON${NORMAL}:$PS1" - fi - if [ "$LAGOON_GIT_BRANCH" ]; then - # production environments get a red color - if [ "$LAGOON_ENVIRONMENT_TYPE" == "production" ]; then - PS1="${RED}$LAGOON_GIT_BRANCH${NORMAL}@$PS1" - else - PS1="${BLUE}$LAGOON_GIT_BRANCH${NORMAL}@$PS1" - fi - fi - if [ "$LAGOON_PROJECT" ]; then - PS1="[${WHITE}$LAGOON_PROJECT${NORMAL}]$PS1" - fi -fi - -# Helpers -alias ll="ls -l" diff --git a/images/commons/Dockerfile b/images/commons/Dockerfile deleted file mode 100644 index 5a906e06a..000000000 --- a/images/commons/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM alpine - -LABEL maintainer="amazee.io" - -ENV LAGOON=commons - -COPY lagoon/ /lagoon/ -RUN mkdir -p /lagoon/bin -COPY fix-permissions docker-sleep /bin/ -COPY .bashrc /home/.bashrc - -RUN apk update \ - && apk upgrade \ - && apk add --no-cache curl tini \ - && rm -rf /var/cache/apk/* \ - && curl -sLo /bin/ep https://github.com/kreuzwerker/envplate/releases/download/1.0.0-RC1/ep-linux \ - && echo "48e234e067874a57a4d4bb198b5558d483ee37bcc285287fffb3864818b42f2785be0568faacbc054e97ca1c5047ec70382e1ca0e71182c9dba06649ad83a5f6 /bin/ep" | sha512sum -c \ - && chmod +x /bin/ep \ - && curl -sLo /lagoon/bin/cron https://github.com/christophlehmann/go-crond/releases/download/0.6.1-2-g7022a21/go-crond-64-linux \ - && echo "4ecbf269a00416086a855b760b6a691d1b8a6385adb18debec893bdbebccd20822b945c476406e3ca27c784812027c23745048fadc36c4067f12038aff972dce /lagoon/bin/cron" | sha512sum -c \ - && chmod +x /lagoon/bin/cron \ - && mkdir -p /lagoon/crontabs && fix-permissions /lagoon/crontabs \ - && ln -s /home/.bashrc /home/.profile - -RUN chmod g+w /etc/passwd - -ARG LAGOON_VERSION -RUN echo $LAGOON_VERSION > /lagoon/version -ENV LAGOON_VERSION=$LAGOON_VERSION - -ENV TMPDIR=/tmp \ - TMP=/tmp \ - HOME=/home \ - # When Bash is invoked via `sh` it behaves like the old Bourne Shell and sources a file that is given in `ENV` - ENV=/home/.bashrc \ - # When Bash is invoked as non-interactive (like `bash -c command`) it sources a file that is given in `BASH_ENV` - BASH_ENV=/home/.bashrc - -ENTRYPOINT ["/sbin/tini", "--", "/lagoon/entrypoints.sh"] -CMD ["/bin/docker-sleep"] \ No newline at end of file diff --git a/images/commons/docker-sleep b/images/commons/docker-sleep deleted file mode 100755 index 426fb9e2a..000000000 --- a/images/commons/docker-sleep +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -while sleep 3600; do :; done \ No newline at end of file diff --git a/images/commons/fix-permissions b/images/commons/fix-permissions deleted file mode 100755 index 8259c2904..000000000 --- a/images/commons/fix-permissions +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Fix permissions on the given directory to allow group read/write of -# regular files and execute of directories. -find -L "$1" -exec chgrp 0 {} \; -find -L "$1" -exec chmod g+rw {} \; -find -L "$1" -type d -exec chmod g+x {} + diff --git a/images/commons/lagoon/cronjob.sh b/images/commons/lagoon/cronjob.sh deleted file mode 100755 index 06d7c8128..000000000 --- a/images/commons/lagoon/cronjob.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -exit_trap() { - # We want to exit with 0 so OpenShift does not try to restart us - # see https://docs.openshift.com/container-platform/3.6/dev_guide/jobs.html#creating-a-job-known-issues - exit 0 -} - -# on exit, always call exit_trap to always exit with 0 -trap exit_trap EXIT - -echo "$(date --utc +%FT%TZ) CRONJOB: $@" - -sh -c "/lagoon/entrypoints.sh $@" \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints.bash b/images/commons/lagoon/entrypoints.bash deleted file mode 100755 index 8c07b2142..000000000 --- a/images/commons/lagoon/entrypoints.bash +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# This script will be the default ENTRYPOINT for all children docker images. -# It just sources all files within /lagoon/entrypoints/* in an alphabetical order and then runs `exec` on the given parameter. - -if [ -d /lagoon/entrypoints ]; then - for i in /lagoon/entrypoints/*; do - if [ -r $i ]; then - . $i - fi - done - unset i -fi - -exec "$@" \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints.sh b/images/commons/lagoon/entrypoints.sh deleted file mode 100755 index 55cedfac8..000000000 --- a/images/commons/lagoon/entrypoints.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -# This script will be the default ENTRYPOINT for all children docker images. -# It just sources all files within /lagoon/entrypoints/* in an alphabetical order and then runs `exec` on the given parameter. - -if [ -d /lagoon/entrypoints ]; then - for i in /lagoon/entrypoints/*; do - if [ -r $i ]; then - . $i - fi - done - unset i -fi - -exec "$@" \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints/00-umask.sh b/images/commons/lagoon/entrypoints/00-umask.sh deleted file mode 100755 index 1f70ab745..000000000 --- a/images/commons/lagoon/entrypoints/00-umask.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# Make sure that new files generated by Docker have group write permission -umask 002 \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints/10-passwd.sh b/images/commons/lagoon/entrypoints/10-passwd.sh deleted file mode 100644 index 09aff906c..000000000 --- a/images/commons/lagoon/entrypoints/10-passwd.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -if [ -w /etc/passwd ]; then - # Change root's home folder to /home - # (we can't use `sed -i` as we sed would create the tempfile in /etc) - TMPFILE=$(mktemp -p /tmp passwd.XXXXXX) - sed 's/root:\/root:/root:\/home:/' /etc/passwd > "$TMPFILE" - cat "$TMPFILE" > /etc/passwd - rm "$TMPFILE" - - # If we don't know who we are (whoami returns false) add a new entry into the users list - if ! whoami &> /dev/null; then - echo "${USER_NAME:-user}:x:$(id -u):0:${USER_NAME:-user}:${HOME}:/bin/sh" >> /etc/passwd - fi -fi diff --git a/images/commons/lagoon/entrypoints/50-dotenv.sh b/images/commons/lagoon/entrypoints/50-dotenv.sh deleted file mode 100644 index 05659ae2e..000000000 --- a/images/commons/lagoon/entrypoints/50-dotenv.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -# dotenv implementation in Bash: -# We basically search for files within the current working directory (defined by WORKDIR in the Dockerfile). -# If it exists, we source them, which means their variables will exist as environment variables for all next processes -# The files are expected to be in this format: -# -# var1=value -# VAR2=value -# -# As there can already be env variables defined in either the Dockerfile of during runtime (via docker run), we have an hierarchy of Environment variables: -# (env variables defined in lower numbers are stronger) -# 1. Runtime env variables (docker run) -# 2. Env variables defined in Dockerfile (ENV) -# 3. Env variables defined in `.lagoon.env.$BRANCHNAME` (if file exists and where $BRANCHNAME is the Branch this Dockerimage has been built for), -# use this for overwriting variables for only specific branches -# 4. Env variables defined in `.env` -# 5. Env variables defined in `.env.defaults` - -# first export all current environment variables into a file. -# We do that in order to keep the hierarchy of environment variables. Already defined ones are probably overwritten -# via an `docker run -e VAR=VAL` system and they should still be used even they are defined in dotenv files. -TMPFILE=$(mktemp -t dotenv.XXXXXXXX) -export -p > $TMPFILE - -# set -a is short for `set -o allexport` which will export all variables in a file -set -a -[ -f .env.defaults ] && . ./.env.defaults || true -[ -f .env ] && . ./.env || true -[ -f .lagoon.env.$LAGOON_GIT_BRANCH ] && . ./.lagoon.env.$LAGOON_GIT_BRANCH || true -# Branch names can have weird special chars in them which are not allowed in File names, so we also try the Branch name with special chars replaced by dashes. -[ -f .lagoon.env.$LAGOON_GIT_SAFE_BRANCH ] && . ./.lagoon.env.$LAGOON_GIT_SAFE_BRANCH || true -set +a - -# now export all previously existing environments variables so they are stronger than maybe existing ones in the dotenv files -. $TMPFILE || true - -# remove the tmpfile -rm $TMPFILE \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints/55-generate-env.sh b/images/commons/lagoon/entrypoints/55-generate-env.sh deleted file mode 100644 index dc9aaa778..000000000 --- a/images/commons/lagoon/entrypoints/55-generate-env.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -# Create a LAGOON_DOMAIN from LAGOON_ROUTE but without the scheme (http:// or https://) -export LAGOON_DOMAIN=${LAGOON_ROUTE#*://} \ No newline at end of file diff --git a/images/commons/lagoon/entrypoints/90-cronjobs.sh b/images/commons/lagoon/entrypoints/90-cronjobs.sh deleted file mode 100644 index c53b6a7d9..000000000 --- a/images/commons/lagoon/entrypoints/90-cronjobs.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# Only if $CRONJOBS is not empty and /lagoon/crontabs/crontab is not existing yet -if [ -x /lagoon/bin/cron ] && [ ! -z "$CRONJOBS" ] && [ ! -f /lagoon/crontabs/crontab ]; then - echo "Setting up Cronjobs:" - echo "${CRONJOBS}" - echo "${CRONJOBS}" > /lagoon/crontabs/crontab - # go-crond does not like if group and others have write access to the crontab - chmod go-w /lagoon/crontabs/crontab - /lagoon/bin/cron $(whoami):/lagoon/crontabs/crontab --allow-unprivileged --no-auto -v & -fi \ No newline at end of file diff --git a/images/curator/Dockerfile b/images/curator/Dockerfile deleted file mode 100644 index 5b85631cb..000000000 --- a/images/curator/Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -ARG IMAGE_REPO -FROM ${IMAGE_REPO:-lagoon}/commons as commons -FROM bobrik/curator - -USER root - -LABEL maintainer="amazee.io" -ENV LAGOON=curator - -ARG LAGOON_VERSION -ENV LAGOON_VERSION=$LAGOON_VERSION - -# Copy commons files -COPY --from=commons /lagoon /lagoon -COPY --from=commons /bin/fix-permissions /bin/ep /bin/docker-sleep /bin/ -COPY --from=commons /home /home - -RUN apk add --no-cache tini \ - && chmod g+w /etc/passwd \ - && mkdir -p /home - -ENV TMPDIR=/tmp \ - TMP=/tmp \ - HOME=/home \ - # When Bash is invoked via `sh` it behaves like the old Bourne Shell and sources a file that is given in `ENV` - ENV=/home/.bashrc \ - # When Bash is invoked as non-interactive (like `bash -c command`) it sources a file that is given in `BASH_ENV` - BASH_ENV=/home/.bashrc - -RUN mkdir -p /curator - -WORKDIR /curator - -ENTRYPOINT ["/sbin/tini", "--", "/lagoon/entrypoints.sh"] - -CMD ["/bin/docker-sleep"] diff --git a/images/docker-host/Dockerfile b/images/docker-host/Dockerfile deleted file mode 100644 index 28d05de38..000000000 --- a/images/docker-host/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -ARG IMAGE_REPO -FROM ${IMAGE_REPO:-lagoon}/commons as commons -FROM docker:stable-dind - -LABEL maintainer="amazee.io" -ENV LAGOON=docker-host - -ARG LAGOON_VERSION -ENV LAGOON_VERSION=$LAGOON_VERSION - -# Copy commons files -COPY --from=commons /lagoon /lagoon -COPY --from=commons /bin/fix-permissions /bin/ep /bin/docker-sleep /bin/ -COPY --from=commons /sbin/tini /sbin/ -COPY --from=commons /home /home - -ENV TMPDIR=/tmp \ - TMP=/tmp \ - HOME=/home \ - # When Bash is invoked via `sh` it behaves like the old Bourne Shell and sources a file that is given in `ENV` - ENV=/home/.bashrc \ - # When Bash is invoked as non-interactive (like `bash -c command`) it sources a file that is given in `BASH_ENV` - BASH_ENV=/home/.bashrc - -RUN apk add --no-cache bash - -ENV DOCKER_HOST=docker-host \ - OPENSHIFT_REGISTRY=docker-registry.default.svc:5000 \ - REPOSITORY_TO_UPDATE=amazeeio - -RUN fix-permissions /home - -COPY update-push-images.sh /update-push-images.sh -COPY prune-images.sh /prune-images.sh - -ENTRYPOINT ["/sbin/tini", "--", "/lagoon/entrypoints.sh"] - -CMD ["sh", "-c", "sh /usr/local/bin/dind /usr/local/bin/dockerd --host=tcp://0.0.0.0:2375 --host=unix:///var/run/docker.sock --insecure-registry=${OPENSHIFT_REGISTRY} --storage-driver=overlay2 --storage-opt=overlay2.override_kernel_check=1"] \ No newline at end of file diff --git a/images/docker-host/prune-images.sh b/images/docker-host/prune-images.sh deleted file mode 100755 index 5bf2b8ace..000000000 --- a/images/docker-host/prune-images.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -x -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -docker image prune -f \ No newline at end of file diff --git a/images/docker-host/update-push-images.sh b/images/docker-host/update-push-images.sh deleted file mode 100755 index edf90db6d..000000000 --- a/images/docker-host/update-push-images.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -e -set -x -OPENSHIFT_PROJECT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - -if ! docker -H ${DOCKER_HOST} info &> /dev/null; then - echo "could not connect to ${DOCKER_HOST}"; exit 1 -fi - -docker login -u=serviceaccount --password-stdin ${OPENSHIFT_REGISTRY} < /var/run/secrets/kubernetes.io/serviceaccount/token - -# Iterates through all images that have the name of the repository we are interested in in it -for FULL_IMAGE in $(docker image ls --format "{{.Repository}}:{{.Tag}}" | grep "${REPOSITORY_TO_UPDATE}/" | grep -v none); do - IMAGE=(${FULL_IMAGE//// }) - if [ ${#IMAGE[@]} == "3" ]; then - IMAGE_NO_REPOSITORY=${IMAGE[2]} - else - IMAGE_NO_REPOSITORY=${IMAGE[1]} - fi - - # pull newest version of found image - docker pull ${FULL_IMAGE} | cat - # Tag the image with the openshift registry name and the openshift project this container is running - docker tag ${FULL_IMAGE} ${OPENSHIFT_REGISTRY}/${OPENSHIFT_PROJECT}/${IMAGE_NO_REPOSITORY} - # Push to the openshift registry - docker push ${OPENSHIFT_REGISTRY}/${OPENSHIFT_PROJECT}/${IMAGE_NO_REPOSITORY} -done \ No newline at end of file diff --git a/images/elasticsearch/Dockerfile b/images/elasticsearch/Dockerfile deleted file mode 100644 index ca744d0d1..000000000 --- a/images/elasticsearch/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -ARG IMAGE_REPO -FROM ${IMAGE_REPO:-lagoon}/commons as commons -FROM docker.elastic.co/elasticsearch/elasticsearch:6.6.1 - -LABEL maintainer="amazee.io" -ENV LAGOON=elasticsearch - -ARG LAGOON_VERSION -ENV LAGOON_VERSION=$LAGOON_VERSION - -# Copy commons files -COPY --from=commons /lagoon /lagoon -COPY --from=commons /bin/fix-permissions /bin/ep /bin/docker-sleep /bin/ -COPY --from=commons /home /home - -RUN curl -sL https://github.com/krallin/tini/releases/download/v0.18.0/tini -o /sbin/tini && chmod a+x /sbin/tini - -COPY peer-finder /bin/ -COPY configure-es.sh /lagoon/ -COPY docker-entrypoint.sh /lagoon/entrypoints/90-elasticsearch.sh - -RUN chmod g+w /etc/passwd \ - && mkdir -p /home - -# Reproduce behavior of Alpine: Run Bash as sh -RUN rm -f /bin/sh && ln -s /bin/bash /bin/sh - -ENV TMPDIR=/tmp \ - TMP=/tmp \ - HOME=/home \ - # When Bash is invoked via `sh` it behaves like the old Bourne Shell and sources a file that is given in `ENV` - ENV=/home/.bashrc \ - # When Bash is invoked as non-interactive (like `bash -c command`) it sources a file that is given in `BASH_ENV` - BASH_ENV=/home/.bashrc - -RUN sed -i 's/discovery.zen.minimum_master_nodes: 1//' config/elasticsearch.yml - -RUN echo $'xpack.security.enabled: false\n\ -\n\ -node.name: "${HOSTNAME}"\n\ -node.master: "${NODE_MASTER}"\n\ -discovery.zen.minimum_master_nodes: "${DISCOVERY_ZEN_MINIMUM_MASTER_NODES}"' >> config/elasticsearch.yml - -RUN fix-permissions config - -ENV ES_JAVA_OPTS="-Xms200m -Xmx200m" \ - DISCOVERY_ZEN_MINIMUM_MASTER_NODES=1 \ - NODE_MASTER=true - -VOLUME [ "/usr/share/elasticsearch/data" ] - -ENTRYPOINT ["/sbin/tini", "--", "/lagoon/entrypoints.bash"] - -CMD ["/usr/local/bin/docker-entrypoint.sh"] diff --git a/images/elasticsearch/configure-es.sh b/images/elasticsearch/configure-es.sh deleted file mode 100755 index d4c18c6a0..000000000 --- a/images/elasticsearch/configure-es.sh +++ /dev/null @@ -1,44 +0,0 @@ -#! /bin/bash - -# Copyright 2016 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -CFG=/usr/share/elasticsearch/config/elasticsearch.yml - - -function join { - local IFS="$1"; shift; echo "$*"; -} - -HOSTNAME=$(hostname) -# Parse out cluster name, from service name: -CLUSTER_NAME="$(hostname -f | cut -d'.' -f2)" - -while read -ra LINE; do - if [[ "${LINE}" == *"${HOSTNAME}"* ]]; then - MY_NAME=$LINE - fi - PEERS=("${PEERS[@]}" $LINE) -done - -if [ "${#PEERS[@]}" = 1 ]; then - ES_CLUSTER_ADDRESS="$MY_NAME" -else - ES_CLUSTER_ADDRESS=$(join , "${PEERS[@]}") -fi - -echo "discovery.zen.ping.unicast.hosts: ${ES_CLUSTER_ADDRESS}" >> ${CFG} - -# don't need a restart, we're just writing the conf in case there's an -# unexpected restart on the node. diff --git a/images/elasticsearch/docker-entrypoint.sh b/images/elasticsearch/docker-entrypoint.sh deleted file mode 100755 index 2902d8997..000000000 --- a/images/elasticsearch/docker-entrypoint.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -eo pipefail - -if [ -z "$POD_NAMESPACE" ]; then - # Single container runs in docker - echo "POD_NAMESPACE not set, spin up single node" -else - # Is running in Kubernetes/OpenShift, so find all other pods - # belonging to the namespace - echo "Elasticsearch: Finding peers" - K8S_SVC_NAME=$(hostname -f | cut -d"." -f2) - echo "Using service name: ${K8S_SVC_NAME}" - # copy the pristine version to the one that can be edited - /usr/bin/peer-finder -on-start="/lagoon/configure-es.sh" -service=${K8S_SVC_NAME} -fi \ No newline at end of file diff --git a/images/elasticsearch/peer-finder b/images/elasticsearch/peer-finder deleted file mode 100755 index 45ed770b2e529a36d19338796f4b27039b9689e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2267197 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⪰!!vGlSj!VBOEe_8ft_u91k!iB6dWnI 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

    !ZmfWN6;CG?q?%tV!tGm(j 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

    rMd9j+kzsr88WQ)ym(^<~HU=PgA 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%0D(~ceS6BYr*JI6?q@5Ol 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 z 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

8(j?!S&CGoO@a*nv}Cp($g0PJg~x^9$it#M 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